From b391b0b5b4f22ec8eeceb5f13aadddf981bc7352 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Sun, 9 Jun 2024 20:47:08 -0400 Subject: [PATCH 01/31] initial struct --- Cargo.toml | 30 ++++++--- arith/Cargo.toml | 11 ++-- bi-kzg/Cargo.toml | 12 ++++ bi-kzg/src/lib.rs | 151 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 188 insertions(+), 16 deletions(-) create mode 100644 bi-kzg/Cargo.toml create mode 100644 bi-kzg/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index eb72ebb2..5a7f409e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,19 +6,29 @@ default-run = "expander-rs" # default [dependencies] arith = { path = "arith" } -ark-std = "0.4" -clap = { version = "4.1", features = ["derive"] } -log = "0.4" -rand = "0.8.5" -sha2 = "0.10.8" -halo2curves = { git = "https://github.com/zhenfeizhang/halo2curves", default-features = false, features = [ "bits" ] } +ark-std.workspace = true +clap.workspace = true +halo2curves.workspace = true +log.workspace = true +rand.workspace = true +sha2.workspace = true + +[[bin]] +name = "expander-exec" +path = "src/exec.rs" [workspace] members = [ - "arith" + "arith", + "bi-kzg" ] -[[bin]] -name = "expander-exec" -path = "src/exec.rs" +[workspace.dependencies] +ark-std = "0.4" +clap = { version = "4.1", features = ["derive"] } +log = "0.4" +rand = "0.8.5" +sha2 = "0.10.8" + +halo2curves = { git = "https://github.com/zhenfeizhang/halo2curves", default-features = false, features = [ "bits", "asm", "bn256-table" ] } diff --git a/arith/Cargo.toml b/arith/Cargo.toml index e8c971b6..26d98489 100644 --- a/arith/Cargo.toml +++ b/arith/Cargo.toml @@ -4,11 +4,10 @@ version = "0.1.0" edition = "2021" [dependencies] -ark-std = "0.4" -log = "0.4" -rand = "0.8.5" -sha2 = "0.10.8" - -halo2curves = { git = "https://github.com/zhenfeizhang/halo2curves", default-features = false, features = [ "bits" ] } +ark-std.workspace = true +halo2curves.workspace = true +log.workspace = true +rand.workspace = true +sha2.workspace = true [features] \ No newline at end of file diff --git a/bi-kzg/Cargo.toml b/bi-kzg/Cargo.toml new file mode 100644 index 00000000..3dea9919 --- /dev/null +++ b/bi-kzg/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "bi-kzg" +version = "0.1.0" +edition = "2021" + +[dependencies] +ark-std.workspace = true +clap.workspace = true +halo2curves.workspace = true +log.workspace = true +rand.workspace = true +sha2.workspace = true \ No newline at end of file diff --git a/bi-kzg/src/lib.rs b/bi-kzg/src/lib.rs new file mode 100644 index 00000000..a395c379 --- /dev/null +++ b/bi-kzg/src/lib.rs @@ -0,0 +1,151 @@ +use std::{borrow::Borrow, fmt::Debug, hash::Hash}; + +use halo2curves::{ff::Field, pairing::Engine, serde::SerdeObject}; +use rand::Rng; + +/// This trait defines APIs for polynomial commitment schemes. +/// Note that for our usage of PCS, we do not require the hiding property. +/// +/// Credit: https://github.com/EspressoSystems/hyperplonk/blob/8698369edfe82bd6617a9609602380f21cabd1da/subroutines/src/pcs/mod.rs#L24 +pub trait PolynomialCommitmentScheme { + /// Prover parameters + type ProverParam: Clone + Sync; + /// Verifier parameters + type VerifierParam: Clone + SerdeObject; + /// Structured reference string + type SRS: Clone + Debug; + /// Polynomial and its associated types + type Polynomial: Clone + Debug + Hash + PartialEq + Eq; + /// Polynomial input domain + type Point: Clone + Ord + Debug + Sync + Hash + PartialEq + Eq; + /// Polynomial Evaluation + type Evaluation: Field; + /// Commitments + type Commitment: Clone + SerdeObject + Debug + PartialEq + Eq; + /// Proofs + type Proof: Clone + SerdeObject + Debug + PartialEq + Eq; + /// Batch proofs + type BatchProof; + + /// Build SRS for testing. + /// + /// - For univariate polynomials, `supported_size` is the maximum degree. + /// - For multilinear polynomials, `supported_size` is the number of + /// variables. + /// + /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY. + /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION. + fn gen_srs_for_testing(rng: &mut R, supported_size: usize) -> Self::SRS; + + /// Trim the universal parameters to specialize the public parameters. + /// Input both `supported_degree` for univariate and + /// `supported_num_vars` for multilinear. + /// ## Note on function signature + /// Usually, data structure like SRS and ProverParam are huge and users + /// might wish to keep them in heap using different kinds of smart pointers + /// (instead of only in stack) therefore our `impl Borrow<_>` interface + /// allows for passing in any pointer type, e.g.: `trim(srs: &Self::SRS, + /// ..)` or `trim(srs: Box, ..)` or `trim(srs: Arc, + /// ..)` etc. + fn trim( + srs: impl Borrow, + supported_degree: Option, + supported_num_vars: Option, + ) -> (Self::ProverParam, Self::VerifierParam); + + /// Generate a commitment for a polynomial + /// ## Note on function signature + /// Usually, data structure like SRS and ProverParam are huge and users + /// might wish to keep them in heap using different kinds of smart pointers + /// (instead of only in stack) therefore our `impl Borrow<_>` interface + /// allows for passing in any pointer type, e.g.: `commit(prover_param: + /// &Self::ProverParam, ..)` or `commit(prover_param: + /// Box, ..)` or `commit(prover_param: + /// Arc, ..)` etc. + fn commit( + prover_param: impl Borrow, + poly: &Self::Polynomial, + ) -> Self::Commitment; + + /// On input a polynomial `p` and a point `point`, outputs a proof for the + /// same. + fn open( + prover_param: impl Borrow, + polynomial: &Self::Polynomial, + point: &Self::Point, + ) -> (Self::Proof, Self::Evaluation); + + /// Input a list of multilinear extensions, and a same number of points, and + /// a transcript, compute a multi-opening for all the polynomials. + fn multi_open( + _prover_param: impl Borrow, + _polynomials: &[Self::Polynomial], + _points: &[Self::Point], + _evals: &[Self::Evaluation], + // _transcript: &mut IOPTranscript, + ) -> Self::BatchProof { + // the reason we use unimplemented!() is to enable developers to implement the + // trait without always implementing the batching APIs. + unimplemented!() + } + + /// Verifies that `value` is the evaluation at `x` of the polynomial + /// committed inside `comm`. + fn verify( + verifier_param: &Self::VerifierParam, + commitment: &Self::Commitment, + point: &Self::Point, + value: &Self::Evaluation, + proof: &Self::Proof, + ) -> bool; + + /// Verifies that `value_i` is the evaluation at `x_i` of the polynomial + /// `poly_i` committed inside `comm`. + fn batch_verify( + _verifier_param: &Self::VerifierParam, + _commitments: &[Self::Commitment], + _points: &[Self::Point], + _batch_proof: &Self::BatchProof, + // _transcript: &mut IOPTranscript, + ) -> bool { + // the reason we use unimplemented!() is to enable developers to implement the + // trait without always implementing the batching APIs. + unimplemented!() + } +} + +/// API definitions for structured reference string +/// +/// Credit: https://github.com/EspressoSystems/hyperplonk/blob/8698369edfe82bd6617a9609602380f21cabd1da/subroutines/src/pcs/mod.rs#L135 +pub trait StructuredReferenceString: Sized { + /// Prover parameters + type ProverParam; + /// Verifier parameters + type VerifierParam; + + /// Extract the prover parameters from the public parameters. + fn extract_prover_param(&self, supported_size: usize) -> Self::ProverParam; + /// Extract the verifier parameters from the public parameters. + fn extract_verifier_param(&self, supported_size: usize) -> Self::VerifierParam; + + /// Trim the universal parameters to specialize the public parameters + /// for polynomials to the given `supported_size`, and + /// returns committer key and verifier key. + /// + /// - For univariate polynomials, `supported_size` is the maximum degree. + /// - For multilinear polynomials, `supported_size` is 2 to the number of + /// variables. + /// + /// `supported_log_size` should be in range `1..=params.log_size` + fn trim(&self, supported_size: usize) -> (Self::ProverParam, Self::VerifierParam); + + /// Build SRS for testing. + /// + /// - For univariate polynomials, `supported_size` is the maximum degree. + /// - For multilinear polynomials, `supported_size` is the number of + /// variables. + /// + /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY. + /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION. + fn gen_srs_for_testing(rng: &mut R, supported_size: usize) -> Self; +} From c8872bcf849be806ea9885dd7fcc40c4bcef1239 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Sun, 9 Jun 2024 21:09:13 -0400 Subject: [PATCH 02/31] skeleton --- bi-kzg/src/bi_kzg.rs | 81 ++++++++++++++++++++++ bi-kzg/src/lib.rs | 154 ++---------------------------------------- bi-kzg/src/pcs.rs | 151 +++++++++++++++++++++++++++++++++++++++++ bi-kzg/src/structs.rs | 121 +++++++++++++++++++++++++++++++++ 4 files changed, 357 insertions(+), 150 deletions(-) create mode 100644 bi-kzg/src/bi_kzg.rs create mode 100644 bi-kzg/src/pcs.rs create mode 100644 bi-kzg/src/structs.rs diff --git a/bi-kzg/src/bi_kzg.rs b/bi-kzg/src/bi_kzg.rs new file mode 100644 index 00000000..7b1bbd06 --- /dev/null +++ b/bi-kzg/src/bi_kzg.rs @@ -0,0 +1,81 @@ +use std::{borrow::Borrow, marker::PhantomData}; + +use halo2curves::pairing::Engine; +use rand::Rng; + +use crate::{ + pcs::PolynomialCommitmentScheme, BiKZGCommitment, BiKZGProof, BiKZGProverParam, BiKZGSRS, + BiKZGVerifierParam, +}; + +pub struct BiKZG { + _engine: PhantomData, +} + +impl PolynomialCommitmentScheme for BiKZG { + type SRS = BiKZGSRS; + type ProverParam = BiKZGProverParam; + type VerifierParam = BiKZGVerifierParam; + type Polynomial = Vec; + type Commitment = BiKZGCommitment; + type Proof = BiKZGProof; + type Evaluation = E::Fr; + type Point = E::Fr; + type BatchProof = Vec; + + fn gen_srs_for_testing(rng: &mut R, supported_size: usize) -> Self::SRS { + unimplemented!() + } + + fn trim( + srs: impl Borrow, + supported_degree: Option, + supported_num_vars: Option, + ) -> (Self::ProverParam, Self::VerifierParam) { + unimplemented!() + } + + fn commit( + prover_param: impl Borrow, + poly: &Self::Polynomial, + ) -> Self::Commitment { + unimplemented!() + } + + fn open( + prover_param: impl Borrow, + polynomial: &Self::Polynomial, + point: &Self::Point, + ) -> (Self::Proof, Self::Evaluation) { + unimplemented!() + } + + fn verify( + verifier_param: &Self::VerifierParam, + commitment: &Self::Commitment, + point: &Self::Point, + value: &Self::Evaluation, + proof: &Self::Proof, + ) -> bool { + unimplemented!() + } + + fn multi_open( + _prover_param: impl Borrow, + _polynomials: &[Self::Polynomial], + _points: &[Self::Point], + _evals: &[Self::Evaluation], + // _transcript: &mut IOPTranscript, + ) -> Self::BatchProof { + unimplemented!() + } + + fn batch_verify( + _verifier_param: &Self::VerifierParam, + _commitments: &[Self::Commitment], + _points: &[Self::Point], + _batch_proof: &Self::BatchProof, + ) -> bool { + unimplemented!() + } +} diff --git a/bi-kzg/src/lib.rs b/bi-kzg/src/lib.rs index a395c379..f3d55eaf 100644 --- a/bi-kzg/src/lib.rs +++ b/bi-kzg/src/lib.rs @@ -1,151 +1,5 @@ -use std::{borrow::Borrow, fmt::Debug, hash::Hash}; +mod bi_kzg; +mod pcs; +mod structs; -use halo2curves::{ff::Field, pairing::Engine, serde::SerdeObject}; -use rand::Rng; - -/// This trait defines APIs for polynomial commitment schemes. -/// Note that for our usage of PCS, we do not require the hiding property. -/// -/// Credit: https://github.com/EspressoSystems/hyperplonk/blob/8698369edfe82bd6617a9609602380f21cabd1da/subroutines/src/pcs/mod.rs#L24 -pub trait PolynomialCommitmentScheme { - /// Prover parameters - type ProverParam: Clone + Sync; - /// Verifier parameters - type VerifierParam: Clone + SerdeObject; - /// Structured reference string - type SRS: Clone + Debug; - /// Polynomial and its associated types - type Polynomial: Clone + Debug + Hash + PartialEq + Eq; - /// Polynomial input domain - type Point: Clone + Ord + Debug + Sync + Hash + PartialEq + Eq; - /// Polynomial Evaluation - type Evaluation: Field; - /// Commitments - type Commitment: Clone + SerdeObject + Debug + PartialEq + Eq; - /// Proofs - type Proof: Clone + SerdeObject + Debug + PartialEq + Eq; - /// Batch proofs - type BatchProof; - - /// Build SRS for testing. - /// - /// - For univariate polynomials, `supported_size` is the maximum degree. - /// - For multilinear polynomials, `supported_size` is the number of - /// variables. - /// - /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY. - /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION. - fn gen_srs_for_testing(rng: &mut R, supported_size: usize) -> Self::SRS; - - /// Trim the universal parameters to specialize the public parameters. - /// Input both `supported_degree` for univariate and - /// `supported_num_vars` for multilinear. - /// ## Note on function signature - /// Usually, data structure like SRS and ProverParam are huge and users - /// might wish to keep them in heap using different kinds of smart pointers - /// (instead of only in stack) therefore our `impl Borrow<_>` interface - /// allows for passing in any pointer type, e.g.: `trim(srs: &Self::SRS, - /// ..)` or `trim(srs: Box, ..)` or `trim(srs: Arc, - /// ..)` etc. - fn trim( - srs: impl Borrow, - supported_degree: Option, - supported_num_vars: Option, - ) -> (Self::ProverParam, Self::VerifierParam); - - /// Generate a commitment for a polynomial - /// ## Note on function signature - /// Usually, data structure like SRS and ProverParam are huge and users - /// might wish to keep them in heap using different kinds of smart pointers - /// (instead of only in stack) therefore our `impl Borrow<_>` interface - /// allows for passing in any pointer type, e.g.: `commit(prover_param: - /// &Self::ProverParam, ..)` or `commit(prover_param: - /// Box, ..)` or `commit(prover_param: - /// Arc, ..)` etc. - fn commit( - prover_param: impl Borrow, - poly: &Self::Polynomial, - ) -> Self::Commitment; - - /// On input a polynomial `p` and a point `point`, outputs a proof for the - /// same. - fn open( - prover_param: impl Borrow, - polynomial: &Self::Polynomial, - point: &Self::Point, - ) -> (Self::Proof, Self::Evaluation); - - /// Input a list of multilinear extensions, and a same number of points, and - /// a transcript, compute a multi-opening for all the polynomials. - fn multi_open( - _prover_param: impl Borrow, - _polynomials: &[Self::Polynomial], - _points: &[Self::Point], - _evals: &[Self::Evaluation], - // _transcript: &mut IOPTranscript, - ) -> Self::BatchProof { - // the reason we use unimplemented!() is to enable developers to implement the - // trait without always implementing the batching APIs. - unimplemented!() - } - - /// Verifies that `value` is the evaluation at `x` of the polynomial - /// committed inside `comm`. - fn verify( - verifier_param: &Self::VerifierParam, - commitment: &Self::Commitment, - point: &Self::Point, - value: &Self::Evaluation, - proof: &Self::Proof, - ) -> bool; - - /// Verifies that `value_i` is the evaluation at `x_i` of the polynomial - /// `poly_i` committed inside `comm`. - fn batch_verify( - _verifier_param: &Self::VerifierParam, - _commitments: &[Self::Commitment], - _points: &[Self::Point], - _batch_proof: &Self::BatchProof, - // _transcript: &mut IOPTranscript, - ) -> bool { - // the reason we use unimplemented!() is to enable developers to implement the - // trait without always implementing the batching APIs. - unimplemented!() - } -} - -/// API definitions for structured reference string -/// -/// Credit: https://github.com/EspressoSystems/hyperplonk/blob/8698369edfe82bd6617a9609602380f21cabd1da/subroutines/src/pcs/mod.rs#L135 -pub trait StructuredReferenceString: Sized { - /// Prover parameters - type ProverParam; - /// Verifier parameters - type VerifierParam; - - /// Extract the prover parameters from the public parameters. - fn extract_prover_param(&self, supported_size: usize) -> Self::ProverParam; - /// Extract the verifier parameters from the public parameters. - fn extract_verifier_param(&self, supported_size: usize) -> Self::VerifierParam; - - /// Trim the universal parameters to specialize the public parameters - /// for polynomials to the given `supported_size`, and - /// returns committer key and verifier key. - /// - /// - For univariate polynomials, `supported_size` is the maximum degree. - /// - For multilinear polynomials, `supported_size` is 2 to the number of - /// variables. - /// - /// `supported_log_size` should be in range `1..=params.log_size` - fn trim(&self, supported_size: usize) -> (Self::ProverParam, Self::VerifierParam); - - /// Build SRS for testing. - /// - /// - For univariate polynomials, `supported_size` is the maximum degree. - /// - For multilinear polynomials, `supported_size` is the number of - /// variables. - /// - /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY. - /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION. - fn gen_srs_for_testing(rng: &mut R, supported_size: usize) -> Self; -} +pub use structs::{BiKZGCommitment, BiKZGProof, BiKZGProverParam, BiKZGSRS, BiKZGVerifierParam}; diff --git a/bi-kzg/src/pcs.rs b/bi-kzg/src/pcs.rs new file mode 100644 index 00000000..52ef0e51 --- /dev/null +++ b/bi-kzg/src/pcs.rs @@ -0,0 +1,151 @@ +use std::{borrow::Borrow, fmt::Debug, hash::Hash}; + +use halo2curves::{ff::Field, pairing::Engine, serde::SerdeObject}; +use rand::Rng; + +/// This trait defines APIs for polynomial commitment schemes. +/// Note that for our usage of PCS, we do not require the hiding property. +/// +/// Credit: https://github.com/EspressoSystems/hyperplonk/blob/8698369edfe82bd6617a9609602380f21cabd1da/subroutines/src/pcs/mod.rs#L24 +pub trait PolynomialCommitmentScheme { + /// Prover parameters + type ProverParam: Clone + Sync; + /// Verifier parameters + type VerifierParam: Clone; + /// Structured reference string + type SRS: Clone + Debug; + /// Polynomial and its associated types + type Polynomial: Clone + Debug + PartialEq + Eq; + /// Polynomial input domain + type Point: Clone + Debug + Sync + PartialEq + Eq; + /// Polynomial Evaluation + type Evaluation: Field; + /// Commitments + type Commitment: Clone + SerdeObject + Debug; + /// Proofs + type Proof: Clone + SerdeObject + Debug; + /// Batch proofs + type BatchProof; + + /// Build SRS for testing. + /// + /// - For univariate polynomials, `supported_size` is the maximum degree. + /// - For multilinear polynomials, `supported_size` is the number of + /// variables. + /// + /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY. + /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION. + fn gen_srs_for_testing(rng: &mut R, supported_size: usize) -> Self::SRS; + + /// Trim the universal parameters to specialize the public parameters. + /// Input both `supported_degree` for univariate and + /// `supported_num_vars` for multilinear. + /// ## Note on function signature + /// Usually, data structure like SRS and ProverParam are huge and users + /// might wish to keep them in heap using different kinds of smart pointers + /// (instead of only in stack) therefore our `impl Borrow<_>` interface + /// allows for passing in any pointer type, e.g.: `trim(srs: &Self::SRS, + /// ..)` or `trim(srs: Box, ..)` or `trim(srs: Arc, + /// ..)` etc. + fn trim( + srs: impl Borrow, + supported_degree: Option, + supported_num_vars: Option, + ) -> (Self::ProverParam, Self::VerifierParam); + + /// Generate a commitment for a polynomial + /// ## Note on function signature + /// Usually, data structure like SRS and ProverParam are huge and users + /// might wish to keep them in heap using different kinds of smart pointers + /// (instead of only in stack) therefore our `impl Borrow<_>` interface + /// allows for passing in any pointer type, e.g.: `commit(prover_param: + /// &Self::ProverParam, ..)` or `commit(prover_param: + /// Box, ..)` or `commit(prover_param: + /// Arc, ..)` etc. + fn commit( + prover_param: impl Borrow, + poly: &Self::Polynomial, + ) -> Self::Commitment; + + /// On input a polynomial `p` and a point `point`, outputs a proof for the + /// same. + fn open( + prover_param: impl Borrow, + polynomial: &Self::Polynomial, + point: &Self::Point, + ) -> (Self::Proof, Self::Evaluation); + + /// Input a list of multilinear extensions, and a same number of points, and + /// a transcript, compute a multi-opening for all the polynomials. + fn multi_open( + _prover_param: impl Borrow, + _polynomials: &[Self::Polynomial], + _points: &[Self::Point], + _evals: &[Self::Evaluation], + // _transcript: &mut IOPTranscript, + ) -> Self::BatchProof { + // the reason we use unimplemented!() is to enable developers to implement the + // trait without always implementing the batching APIs. + unimplemented!() + } + + /// Verifies that `value` is the evaluation at `x` of the polynomial + /// committed inside `comm`. + fn verify( + verifier_param: &Self::VerifierParam, + commitment: &Self::Commitment, + point: &Self::Point, + value: &Self::Evaluation, + proof: &Self::Proof, + ) -> bool; + + /// Verifies that `value_i` is the evaluation at `x_i` of the polynomial + /// `poly_i` committed inside `comm`. + fn batch_verify( + _verifier_param: &Self::VerifierParam, + _commitments: &[Self::Commitment], + _points: &[Self::Point], + _batch_proof: &Self::BatchProof, + // _transcript: &mut IOPTranscript, + ) -> bool { + // the reason we use unimplemented!() is to enable developers to implement the + // trait without always implementing the batching APIs. + unimplemented!() + } +} + +/// API definitions for structured reference string +/// +/// Credit: https://github.com/EspressoSystems/hyperplonk/blob/8698369edfe82bd6617a9609602380f21cabd1da/subroutines/src/pcs/mod.rs#L135 +pub trait StructuredReferenceString: Sized { + /// Prover parameters + type ProverParam; + /// Verifier parameters + type VerifierParam; + + /// Extract the prover parameters from the public parameters. + fn extract_prover_param(&self, supported_size: usize) -> Self::ProverParam; + /// Extract the verifier parameters from the public parameters. + fn extract_verifier_param(&self, supported_size: usize) -> Self::VerifierParam; + + /// Trim the universal parameters to specialize the public parameters + /// for polynomials to the given `supported_size`, and + /// returns committer key and verifier key. + /// + /// - For univariate polynomials, `supported_size` is the maximum degree. + /// - For multilinear polynomials, `supported_size` is 2 to the number of + /// variables. + /// + /// `supported_log_size` should be in range `1..=params.log_size` + fn trim(&self, supported_size: usize) -> (Self::ProverParam, Self::VerifierParam); + + /// Build SRS for testing. + /// + /// - For univariate polynomials, `supported_size` is the maximum degree. + /// - For multilinear polynomials, `supported_size` is the number of + /// variables. + /// + /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY. + /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION. + fn gen_srs_for_testing(rng: &mut R, supported_size: usize) -> Self; +} diff --git a/bi-kzg/src/structs.rs b/bi-kzg/src/structs.rs new file mode 100644 index 00000000..39561661 --- /dev/null +++ b/bi-kzg/src/structs.rs @@ -0,0 +1,121 @@ +use std::io::{self, Read, Write}; + +use halo2curves::{pairing::Engine, serde::SerdeObject}; + +/// Structured reference string for Bi-KZG polynomial commitment scheme. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct BiKZGSRS { + /// (g_1^{\tau_0^i\tau_1^j})_{i\in [0,N], j\in [0, M]} = \\ + /// ( + /// g_1, g_1^{\tau_0}, g_1^{\tau_0^2}, ..., g_1^{\tau_0^N}, + /// g_1^{\tau_1}, g_1^{\tau_0\tau_1}, g_1^{\tau_0^2\tau_1}, ..., g_1^{\tau_0^N\tau_1}, + /// ..., g_1^{\tau_0^N\tau_1^M} + /// ) + pub powers_of_g: Vec, + /// The generator of G2. + pub h: E::G2Affine, + /// \beta times the above generator of G2. + pub beta_h: E::G2Affine, +} + +/// `BiKZGProverParam` is used to generate a proof +#[derive(Clone, Debug, Eq, PartialEq, Default)] +pub struct BiKZGProverParam { + /// Parameters + pub powers_of_g: Vec, +} + +/// `UnivariateVerifierParam` is used to check evaluation proofs for a given +/// commitment. +#[derive(Clone, Debug, Eq, PartialEq, Default)] +pub struct BiKZGVerifierParam { + /// The generator of G1. + pub g: E::G1Affine, + /// The generator of G2. + pub h: E::G2Affine, + /// \beta times the above generator of G2. + pub beta_h: E::G2Affine, +} + +/// Commitment Bi-KZG polynomial commitment scheme. +#[derive(Clone, Debug, Default, PartialEq)] +pub struct BiKZGCommitment { + /// the actual commitment is an affine point. + pub com: E::G1Affine, +} + +/// Proof for Bi-KZG polynomial commitment scheme. +#[derive(Clone, Debug, Default, PartialEq)] +pub struct BiKZGProof { + /// the actual proof is a pair of affine points. + pub pi0: E::G1Affine, + pub pi1: E::G1Affine, +} + +impl SerdeObject for BiKZGCommitment { + /// The purpose of unchecked functions is to read the internal memory representation + /// of a type from bytes as quickly as possible. No sanitization checks are performed + /// to ensure the bytes represent a valid object. As such this function should only be + /// used internally as an extension of machine memory. It should not be used to deserialize + /// externally provided data. + fn from_raw_bytes_unchecked(bytes: &[u8]) -> Self { + todo!("Implement this function") + } + fn from_raw_bytes(bytes: &[u8]) -> Option { + todo!("Implement this function") + } + + fn to_raw_bytes(&self) -> Vec { + todo!("Implement this function") + } + + /// The purpose of unchecked functions is to read the internal memory representation + /// of a type from disk as quickly as possible. No sanitization checks are performed + /// to ensure the bytes represent a valid object. This function should only be used + /// internally when some machine state cannot be kept in memory (e.g., between runs) + /// and needs to be reloaded as quickly as possible. + fn read_raw_unchecked(reader: &mut R) -> Self { + todo!("Implement this function") + } + fn read_raw(reader: &mut R) -> io::Result { + todo!("Implement this function") + } + + fn write_raw(&self, writer: &mut W) -> io::Result<()> { + todo!("Implement this function") + } +} + +impl SerdeObject for BiKZGProof { + /// The purpose of unchecked functions is to read the internal memory representation + /// of a type from bytes as quickly as possible. No sanitization checks are performed + /// to ensure the bytes represent a valid object. As such this function should only be + /// used internally as an extension of machine memory. It should not be used to deserialize + /// externally provided data. + fn from_raw_bytes_unchecked(bytes: &[u8]) -> Self { + todo!("Implement this function") + } + fn from_raw_bytes(bytes: &[u8]) -> Option { + todo!("Implement this function") + } + + fn to_raw_bytes(&self) -> Vec { + todo!("Implement this function") + } + + /// The purpose of unchecked functions is to read the internal memory representation + /// of a type from disk as quickly as possible. No sanitization checks are performed + /// to ensure the bytes represent a valid object. This function should only be used + /// internally when some machine state cannot be kept in memory (e.g., between runs) + /// and needs to be reloaded as quickly as possible. + fn read_raw_unchecked(reader: &mut R) -> Self { + todo!("Implement this function") + } + fn read_raw(reader: &mut R) -> io::Result { + todo!("Implement this function") + } + + fn write_raw(&self, writer: &mut W) -> io::Result<()> { + todo!("Implement this function") + } +} From 2dbf0bc41d86b30293615f87bf2694832d2a8d6f Mon Sep 17 00:00:00 2001 From: zhenfei Date: Sun, 9 Jun 2024 22:33:32 -0400 Subject: [PATCH 03/31] finished srs gen --- bi-kzg/Cargo.toml | 1 + bi-kzg/src/bi_kzg.rs | 103 +++++++++++++++++++++++++++++++++++++----- bi-kzg/src/lib.rs | 3 ++ bi-kzg/src/pcs.rs | 34 +++++++------- bi-kzg/src/structs.rs | 12 +++-- bi-kzg/src/tests.rs | 14 ++++++ bi-kzg/src/util.rs | 84 ++++++++++++++++++++++++++++++++++ 7 files changed, 218 insertions(+), 33 deletions(-) create mode 100644 bi-kzg/src/tests.rs create mode 100644 bi-kzg/src/util.rs diff --git a/bi-kzg/Cargo.toml b/bi-kzg/Cargo.toml index 3dea9919..c9b640f8 100644 --- a/bi-kzg/Cargo.toml +++ b/bi-kzg/Cargo.toml @@ -9,4 +9,5 @@ clap.workspace = true halo2curves.workspace = true log.workspace = true rand.workspace = true +rayon.workspace = true sha2.workspace = true \ No newline at end of file diff --git a/bi-kzg/src/bi_kzg.rs b/bi-kzg/src/bi_kzg.rs index 7b1bbd06..c879bc9f 100644 --- a/bi-kzg/src/bi_kzg.rs +++ b/bi-kzg/src/bi_kzg.rs @@ -1,11 +1,21 @@ -use std::{borrow::Borrow, marker::PhantomData}; +use std::{borrow::Borrow, marker::PhantomData, slice::ChunkBy}; + +use halo2curves::ff::Field; +use halo2curves::ff::PrimeField; +use halo2curves::group::prime::PrimeCurveAffine; +use halo2curves::group::Curve; +use halo2curves::group::Group; use halo2curves::pairing::Engine; use rand::Rng; +use rand::RngCore; +use crate::util::lagrange_coefficients; +use crate::util::parallelize; use crate::{ - pcs::PolynomialCommitmentScheme, BiKZGCommitment, BiKZGProof, BiKZGProverParam, BiKZGSRS, - BiKZGVerifierParam, + pcs::PolynomialCommitmentScheme, + util::{powers_of_field_elements, tensor_product_parallel}, + BiKZGCommitment, BiKZGProof, BiKZGProverParam, BiKZGSRS, BiKZGVerifierParam, }; pub struct BiKZG { @@ -23,18 +33,87 @@ impl PolynomialCommitmentScheme for BiKZG { type Point = E::Fr; type BatchProof = Vec; - fn gen_srs_for_testing(rng: &mut R, supported_size: usize) -> Self::SRS { - unimplemented!() - } + fn gen_srs_for_testing( + mut rng: impl RngCore, + supported_n: usize, + supported_m: usize, + ) -> Self::SRS { + assert!(supported_n.is_power_of_two()); + assert!(supported_m.is_power_of_two()); - fn trim( - srs: impl Borrow, - supported_degree: Option, - supported_num_vars: Option, - ) -> (Self::ProverParam, Self::VerifierParam) { - unimplemented!() + let tau_0 = E::Fr::random(&mut rng); + let tau_1 = E::Fr::random(&mut rng); + // let tau_0 = E::Fr::from(5); + // let tau_1 = E::Fr::from(7); + + let g1 = E::G1Affine::generator(); + + // roots of unity for supported_n and supported_m + let (omega_0, omega_1) = { + let omega = E::Fr::ROOT_OF_UNITY; + let omega_0 = omega.pow_vartime(&[(1 << E::Fr::S) / supported_n as u64]); + let omega_1 = omega.pow_vartime(&[(1 << E::Fr::S) / supported_m as u64]); + + assert!( + omega_0.pow_vartime(&[supported_n as u64]) == E::Fr::ONE, + "omega_0 is not root of unity for supported_n" + ); + assert!( + omega_1.pow_vartime(&[supported_m as u64]) == E::Fr::ONE, + "omega_1 is not root of unity for supported_m" + ); + (omega_0, omega_1) + }; + + println!("start to compute the scalars"); + // computes the vector of L_i^N(tau_0) * L_j^M(tau_1) for i in 0..supported_n and j in 0..supported_m + let scalars = { + let powers_of_omega_0 = powers_of_field_elements(omega_0, supported_n); + let powers_of_tau_0 = powers_of_field_elements(tau_0, supported_n); + let lagrange_tau_0 = lagrange_coefficients(&powers_of_omega_0, &powers_of_tau_0); + let powers_of_omega_1 = powers_of_field_elements(omega_1, supported_m); + let powers_of_tau_1 = powers_of_field_elements(tau_1, supported_m); + let lagrange_tau_1 = lagrange_coefficients(&powers_of_omega_1, &powers_of_tau_1); + tensor_product_parallel(&lagrange_tau_0, &lagrange_tau_1) + }; + + println!("start to compute the affine bases"); + let affine_bases = { + let mut proj_bases = vec![E::G1::identity(); supported_n * supported_m]; + parallelize(&mut proj_bases, |g, start| { + for (idx, g) in g.iter_mut().enumerate() { + let offset = start + idx; + *g = g1 * scalars[offset]; + } + }); + + let mut g_lagrange = vec![E::G1Affine::identity(); supported_n * supported_m]; + parallelize(&mut g_lagrange, |g_lagrange, starts| { + E::G1::batch_normalize( + &proj_bases[starts..(starts + g_lagrange.len())], + g_lagrange, + ); + }); + drop(proj_bases); + g_lagrange + }; + + BiKZGSRS { + powers_of_g: affine_bases, + h: E::G2Affine::generator(), + tau_0_h: (E::G2Affine::generator() * tau_0).into(), + tau_1_h: (E::G2Affine::generator() * tau_1).into(), + } } + // fn trim( + // srs: impl Borrow, + // supported_degree: Option, + // supported_num_vars: Option, + // ) -> (Self::ProverParam, Self::VerifierParam) { + // unimplemented!() + // } + fn commit( prover_param: impl Borrow, poly: &Self::Polynomial, diff --git a/bi-kzg/src/lib.rs b/bi-kzg/src/lib.rs index f3d55eaf..def5a241 100644 --- a/bi-kzg/src/lib.rs +++ b/bi-kzg/src/lib.rs @@ -1,5 +1,8 @@ mod bi_kzg; mod pcs; mod structs; +#[cfg(test)] +mod tests; +mod util; pub use structs::{BiKZGCommitment, BiKZGProof, BiKZGProverParam, BiKZGSRS, BiKZGVerifierParam}; diff --git a/bi-kzg/src/pcs.rs b/bi-kzg/src/pcs.rs index 52ef0e51..4c6b2f8b 100644 --- a/bi-kzg/src/pcs.rs +++ b/bi-kzg/src/pcs.rs @@ -1,7 +1,7 @@ use std::{borrow::Borrow, fmt::Debug, hash::Hash}; use halo2curves::{ff::Field, pairing::Engine, serde::SerdeObject}; -use rand::Rng; +use rand::{Rng, RngCore}; /// This trait defines APIs for polynomial commitment schemes. /// Note that for our usage of PCS, we do not require the hiding property. @@ -35,23 +35,23 @@ pub trait PolynomialCommitmentScheme { /// /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY. /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION. - fn gen_srs_for_testing(rng: &mut R, supported_size: usize) -> Self::SRS; + fn gen_srs_for_testing(rng: impl RngCore, supported_n: usize, supported_m: usize) -> Self::SRS; - /// Trim the universal parameters to specialize the public parameters. - /// Input both `supported_degree` for univariate and - /// `supported_num_vars` for multilinear. - /// ## Note on function signature - /// Usually, data structure like SRS and ProverParam are huge and users - /// might wish to keep them in heap using different kinds of smart pointers - /// (instead of only in stack) therefore our `impl Borrow<_>` interface - /// allows for passing in any pointer type, e.g.: `trim(srs: &Self::SRS, - /// ..)` or `trim(srs: Box, ..)` or `trim(srs: Arc, - /// ..)` etc. - fn trim( - srs: impl Borrow, - supported_degree: Option, - supported_num_vars: Option, - ) -> (Self::ProverParam, Self::VerifierParam); + // /// Trim the universal parameters to specialize the public parameters. + // /// Input both `supported_degree` for univariate and + // /// `supported_num_vars` for multilinear. + // /// ## Note on function signature + // /// Usually, data structure like SRS and ProverParam are huge and users + // /// might wish to keep them in heap using different kinds of smart pointers + // /// (instead of only in stack) therefore our `impl Borrow<_>` interface + // /// allows for passing in any pointer type, e.g.: `trim(srs: &Self::SRS, + // /// ..)` or `trim(srs: Box, ..)` or `trim(srs: Arc, + // /// ..)` etc. + // fn trim( + // srs: impl Borrow, + // supported_degree: Option, + // supported_num_vars: Option, + // ) -> (Self::ProverParam, Self::VerifierParam); /// Generate a commitment for a polynomial /// ## Note on function signature diff --git a/bi-kzg/src/structs.rs b/bi-kzg/src/structs.rs index 39561661..246a9c9c 100644 --- a/bi-kzg/src/structs.rs +++ b/bi-kzg/src/structs.rs @@ -14,8 +14,10 @@ pub struct BiKZGSRS { pub powers_of_g: Vec, /// The generator of G2. pub h: E::G2Affine, - /// \beta times the above generator of G2. - pub beta_h: E::G2Affine, + /// tau_0 times the above generator of G2. + pub tau_0_h: E::G2Affine, + /// tau_1 times the above generator of G2. + pub tau_1_h: E::G2Affine, } /// `BiKZGProverParam` is used to generate a proof @@ -33,8 +35,10 @@ pub struct BiKZGVerifierParam { pub g: E::G1Affine, /// The generator of G2. pub h: E::G2Affine, - /// \beta times the above generator of G2. - pub beta_h: E::G2Affine, + /// tau_0 times the above generator of G2. + pub tau_0_h: E::G2Affine, + /// tau_1 times the above generator of G2. + pub tau_1_h: E::G2Affine, } /// Commitment Bi-KZG polynomial commitment scheme. diff --git a/bi-kzg/src/tests.rs b/bi-kzg/src/tests.rs new file mode 100644 index 00000000..5900fbe6 --- /dev/null +++ b/bi-kzg/src/tests.rs @@ -0,0 +1,14 @@ +use ark_std::test_rng; +use halo2curves::bn256::Bn256; + +use crate::{bi_kzg::BiKZG, pcs::PolynomialCommitmentScheme}; + +#[test] +fn test_bi_kzg_e2e() { + let mut rng = test_rng(); + let n = 4; + let m = 8; + let srs = BiKZG::::gen_srs_for_testing(&mut rng, n, m); + + assert!(false) +} diff --git a/bi-kzg/src/util.rs b/bi-kzg/src/util.rs new file mode 100644 index 00000000..9c92b467 --- /dev/null +++ b/bi-kzg/src/util.rs @@ -0,0 +1,84 @@ +use halo2curves::ff::Field; +use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; + +pub(crate) fn powers_of_field_elements(x: F, n: usize) -> Vec { + let mut powers = vec![F::ONE]; + let mut cur = x; + for _ in 0..n - 1 { + powers.push(cur); + cur *= x; + } + powers +} + +pub(crate) fn tensor_product_parallel(vec1: &[F], vec2: &[F]) -> Vec { + vec1.par_iter() + .flat_map(|&i| vec2.iter().map(|&j| i * j).collect::>()) + .collect() +} + +/// For x in points, compute the Lagrange coefficients at x given the roots. +/// `L_{i}(x) = \prod_{j \neq i} \frac{x - r_j}{r_i - r_j}`` +pub(crate) fn lagrange_coefficients(roots: &[F], points: &[F]) -> Vec { + roots + .par_iter() + .enumerate() + .map(|(i, _)| { + let mut numerator = F::ONE; + let mut denominator = F::ONE; + for j in 0..roots.len() { + if i == j { + continue; + } + numerator *= roots[j] - points[i]; + denominator *= roots[j] - roots[i]; + } + numerator * denominator.invert().unwrap() + }) + .collect() +} + +/// This simple utility function will parallelize an operation that is to be +/// performed over a mutable slice. +/// credit: https://github.com/scroll-tech/halo2/blob/1070391642dd64b2d68b47ec246cba9e35bd3c15/halo2_proofs/src/arithmetic.rs#L546 +pub(crate) fn parallelize_internal( + v: &mut [T], + f: F, +) -> Vec { + let n = v.len(); + let num_threads = rayon::current_num_threads(); + let mut chunk = (n as usize) / num_threads; + if chunk < num_threads { + chunk = 1; + } + + rayon::scope(|scope| { + let mut chunk_starts = vec![]; + for (chunk_num, v) in v.chunks_mut(chunk).enumerate() { + let f = f.clone(); + scope.spawn(move |_| { + let start = chunk_num * chunk; + f(v, start); + }); + let start = chunk_num * chunk; + chunk_starts.push(start); + } + + chunk_starts + }) +} + +pub fn parallelize(v: &mut [T], f: F) { + parallelize_internal(v, f); +} + +#[test] +fn test_lagrange_eval() { + use halo2curves::bn256::Fr; + let roots = vec![Fr::from(1u64), Fr::from(2u64), Fr::from(3u64)]; + let points = vec![Fr::from(4u64), Fr::from(5u64), Fr::from(6u64)]; + let result = lagrange_coefficients(&roots, &points); + assert_eq!(result[0], Fr::from(1u64)); + assert_eq!(result[1], -Fr::from(8u64)); + assert_eq!(result[2], Fr::from(10u64)); +} From f7272ad767558818665c605c6c07d6f4e642841b Mon Sep 17 00:00:00 2001 From: zhenfei Date: Sun, 9 Jun 2024 22:33:46 -0400 Subject: [PATCH 04/31] update toml --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 5a7f409e..3f9668d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,7 @@ ark-std = "0.4" clap = { version = "4.1", features = ["derive"] } log = "0.4" rand = "0.8.5" +rayon = "1.10" sha2 = "0.10.8" halo2curves = { git = "https://github.com/zhenfeizhang/halo2curves", default-features = false, features = [ "bits", "asm", "bn256-table" ] } From ead0e55475718d65d3285b625fb17ce7c8e6b6b7 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Sun, 9 Jun 2024 22:56:20 -0400 Subject: [PATCH 05/31] add msm; commit --- bi-kzg/src/bi_kzg.rs | 18 +++-- bi-kzg/src/lib.rs | 3 +- bi-kzg/src/msm.rs | 158 ++++++++++++++++++++++++++++++++++++++++++ bi-kzg/src/pcs.rs | 64 ++++++++--------- bi-kzg/src/structs.rs | 23 ++++-- 5 files changed, 223 insertions(+), 43 deletions(-) create mode 100644 bi-kzg/src/msm.rs diff --git a/bi-kzg/src/bi_kzg.rs b/bi-kzg/src/bi_kzg.rs index c879bc9f..4b42ba0d 100644 --- a/bi-kzg/src/bi_kzg.rs +++ b/bi-kzg/src/bi_kzg.rs @@ -1,3 +1,5 @@ +use std::ops::{Add, AddAssign}; +use std::process::Output; use std::{borrow::Borrow, marker::PhantomData, slice::ChunkBy}; use halo2curves::ff::Field; @@ -6,25 +8,31 @@ use halo2curves::group::prime::PrimeCurveAffine; use halo2curves::group::Curve; use halo2curves::group::Group; +// use halo2curves::msm::best_multiexp; use halo2curves::pairing::Engine; +use halo2curves::CurveAffine; use rand::Rng; use rand::RngCore; +use crate::msm::best_multiexp; use crate::util::lagrange_coefficients; use crate::util::parallelize; use crate::{ pcs::PolynomialCommitmentScheme, util::{powers_of_field_elements, tensor_product_parallel}, - BiKZGCommitment, BiKZGProof, BiKZGProverParam, BiKZGSRS, BiKZGVerifierParam, + BiKZGCommitment, BiKZGProof, BiKZGSRS, BiKZGVerifierParam, }; pub struct BiKZG { _engine: PhantomData, } -impl PolynomialCommitmentScheme for BiKZG { +impl PolynomialCommitmentScheme for BiKZG +where + E::G1Affine: Add, +{ type SRS = BiKZGSRS; - type ProverParam = BiKZGProverParam; + type ProverParam = BiKZGSRS; type VerifierParam = BiKZGVerifierParam; type Polynomial = Vec; type Commitment = BiKZGCommitment; @@ -118,7 +126,9 @@ impl PolynomialCommitmentScheme for BiKZG { prover_param: impl Borrow, poly: &Self::Polynomial, ) -> Self::Commitment { - unimplemented!() + Self::Commitment { + com: best_multiexp(poly, prover_param.borrow().powers_of_g.as_slice()).into(), + } } fn open( diff --git a/bi-kzg/src/lib.rs b/bi-kzg/src/lib.rs index def5a241..03f8ccd3 100644 --- a/bi-kzg/src/lib.rs +++ b/bi-kzg/src/lib.rs @@ -1,8 +1,9 @@ mod bi_kzg; +mod msm; mod pcs; mod structs; #[cfg(test)] mod tests; mod util; -pub use structs::{BiKZGCommitment, BiKZGProof, BiKZGProverParam, BiKZGSRS, BiKZGVerifierParam}; +pub use structs::{BiKZGCommitment, BiKZGProof, BiKZGSRS, BiKZGVerifierParam}; diff --git a/bi-kzg/src/msm.rs b/bi-kzg/src/msm.rs new file mode 100644 index 00000000..1836be13 --- /dev/null +++ b/bi-kzg/src/msm.rs @@ -0,0 +1,158 @@ +//! credit: https://github.com/zhenfeizhang/halo2curves/blob/inline/src/msm.rs +//! Code modified to simplify the implementation and remove the need for the `Curve` trait. + +use std::ops::{Add, Neg}; + +use halo2curves::ff::PrimeField; +use halo2curves::pairing::PairingCurveAffine;use halo2curves::group::Group; + +fn get_booth_index(window_index: usize, window_size: usize, el: &[u8]) -> i32 { + // Booth encoding: + // * step by `window` size + // * slice by size of `window + 1`` + // * each window overlap by 1 bit + // * append a zero bit to the least significant end + // Indexing rule for example window size 3 where we slice by 4 bits: + // `[0, +1, +1, +2, +2, +3, +3, +4, -4, -3, -3 -2, -2, -1, -1, 0]`` + // So we can reduce the bucket size without preprocessing scalars + // and remembering them as in classic signed digit encoding + + let skip_bits = (window_index * window_size).saturating_sub(1); + let skip_bytes = skip_bits / 8; + + // fill into a u32 + let mut v: [u8; 4] = [0; 4]; + for (dst, src) in v.iter_mut().zip(el.iter().skip(skip_bytes)) { + *dst = *src + } + let mut tmp = u32::from_le_bytes(v); + + // pad with one 0 if slicing the least significant window + if window_index == 0 { + tmp <<= 1; + } + + // remove further bits + tmp >>= skip_bits - (skip_bytes * 8); + // apply the booth window + tmp &= (1 << (window_size + 1)) - 1; + + let sign = tmp & (1 << window_size) == 0; + + // div ceil by 2 + tmp = (tmp + 1) >> 1; + + // find the booth action index + if sign { + tmp as i32 + } else { + ((!(tmp - 1) & ((1 << window_size) - 1)) as i32).neg() + } +} + +/// Performs a multi-exponentiation operation. +/// +/// This function will panic if coeffs and bases have a different length. +/// +/// This will use multithreading if beneficial. +pub fn best_multiexp>(coeffs: &[C::Scalar], bases: &[C]) -> C::Curve { + assert_eq!(coeffs.len(), bases.len()); + + let num_threads = rayon::current_num_threads(); + if coeffs.len() > num_threads { + let chunk = coeffs.len() / num_threads; + let num_chunks = coeffs.chunks(chunk).len(); + let mut results = vec![C::Curve::identity(); num_chunks]; + rayon::scope(|scope| { + let chunk = coeffs.len() / num_threads; + + for ((coeffs, bases), acc) in coeffs + .chunks(chunk) + .zip(bases.chunks(chunk)) + .zip(results.iter_mut()) + { + scope.spawn(move |_| { + multiexp_serial(coeffs, bases, acc); + }); + } + }); + results.iter().fold(C::Curve::identity(), |a, b| a + b) + } else { + let mut acc = C::Curve::identity(); + multiexp_serial(coeffs, bases, &mut acc); + acc + } +} + +pub fn multiexp_serial>(coeffs: &[C::Scalar], bases: &[C], acc: &mut C::Curve) { + let coeffs: Vec<_> = coeffs.iter().map(|a| a.to_repr()).collect(); + + let c = if bases.len() < 4 { + 1 + } else if bases.len() < 32 { + 3 + } else { + (f64::from(bases.len() as u32)).ln().ceil() as usize + }; + + let number_of_windows = C::Scalar::NUM_BITS as usize / c + 1; + + for current_window in (0..number_of_windows).rev() { + for _ in 0..c { + *acc = acc.double(); + } + + #[derive(Clone, Copy)] + enum Bucket { + None, + Affine(C), + Projective(C::Curve), + } + + impl> Bucket { + fn add_assign(&mut self, other: &C) { + *self = match *self { + Bucket::None => Bucket::Affine(*other), + Bucket::Affine(a) => Bucket::Projective(a + *other), + Bucket::Projective(mut a) => { + a += *other; + Bucket::Projective(a) + } + } + } + + fn add(self, mut other: C::Curve) -> C::Curve { + match self { + Bucket::None => other, + Bucket::Affine(a) => { + other += a; + other + } + Bucket::Projective(a) => other + a, + } + } + } + + let mut buckets: Vec> = vec![Bucket::None; 1 << (c - 1)]; + + for (coeff, base) in coeffs.iter().zip(bases.iter()) { + let coeff = get_booth_index(current_window, c, coeff.as_ref()); + if coeff.is_positive() { + buckets[coeff as usize - 1].add_assign(base); + } + if coeff.is_negative() { + buckets[coeff.unsigned_abs() as usize - 1].add_assign(&base.neg()); + } + } + + // Summation by parts + // e.g. 3a + 2b + 1c = a + + // (a) + b + + // ((a) + b) + c + let mut running_sum = C::Curve::identity(); + for exp in buckets.into_iter().rev() { + running_sum = exp.add(running_sum); + *acc += &running_sum; + } + } +} diff --git a/bi-kzg/src/pcs.rs b/bi-kzg/src/pcs.rs index 4c6b2f8b..a2e8afc0 100644 --- a/bi-kzg/src/pcs.rs +++ b/bi-kzg/src/pcs.rs @@ -114,38 +114,38 @@ pub trait PolynomialCommitmentScheme { } } -/// API definitions for structured reference string -/// -/// Credit: https://github.com/EspressoSystems/hyperplonk/blob/8698369edfe82bd6617a9609602380f21cabd1da/subroutines/src/pcs/mod.rs#L135 -pub trait StructuredReferenceString: Sized { - /// Prover parameters - type ProverParam; - /// Verifier parameters - type VerifierParam; +// /// API definitions for structured reference string +// /// +// /// Credit: https://github.com/EspressoSystems/hyperplonk/blob/8698369edfe82bd6617a9609602380f21cabd1da/subroutines/src/pcs/mod.rs#L135 +// pub trait StructuredReferenceString: Sized { +// /// Prover parameters +// type ProverParam; +// /// Verifier parameters +// type VerifierParam; - /// Extract the prover parameters from the public parameters. - fn extract_prover_param(&self, supported_size: usize) -> Self::ProverParam; - /// Extract the verifier parameters from the public parameters. - fn extract_verifier_param(&self, supported_size: usize) -> Self::VerifierParam; +// /// Extract the prover parameters from the public parameters. +// fn extract_prover_param(&self, supported_size: usize) -> Self::ProverParam; +// /// Extract the verifier parameters from the public parameters. +// fn extract_verifier_param(&self, supported_size: usize) -> Self::VerifierParam; - /// Trim the universal parameters to specialize the public parameters - /// for polynomials to the given `supported_size`, and - /// returns committer key and verifier key. - /// - /// - For univariate polynomials, `supported_size` is the maximum degree. - /// - For multilinear polynomials, `supported_size` is 2 to the number of - /// variables. - /// - /// `supported_log_size` should be in range `1..=params.log_size` - fn trim(&self, supported_size: usize) -> (Self::ProverParam, Self::VerifierParam); +// /// Trim the universal parameters to specialize the public parameters +// /// for polynomials to the given `supported_size`, and +// /// returns committer key and verifier key. +// /// +// /// - For univariate polynomials, `supported_size` is the maximum degree. +// /// - For multilinear polynomials, `supported_size` is 2 to the number of +// /// variables. +// /// +// /// `supported_log_size` should be in range `1..=params.log_size` +// fn trim(&self, supported_size: usize) -> (Self::ProverParam, Self::VerifierParam); - /// Build SRS for testing. - /// - /// - For univariate polynomials, `supported_size` is the maximum degree. - /// - For multilinear polynomials, `supported_size` is the number of - /// variables. - /// - /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY. - /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION. - fn gen_srs_for_testing(rng: &mut R, supported_size: usize) -> Self; -} +// /// Build SRS for testing. +// /// +// /// - For univariate polynomials, `supported_size` is the maximum degree. +// /// - For multilinear polynomials, `supported_size` is the number of +// /// variables. +// /// +// /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY. +// /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION. +// fn gen_srs_for_testing(rng: &mut R, supported_size: usize) -> Self; +// } diff --git a/bi-kzg/src/structs.rs b/bi-kzg/src/structs.rs index 246a9c9c..24368ba7 100644 --- a/bi-kzg/src/structs.rs +++ b/bi-kzg/src/structs.rs @@ -20,12 +20,12 @@ pub struct BiKZGSRS { pub tau_1_h: E::G2Affine, } -/// `BiKZGProverParam` is used to generate a proof -#[derive(Clone, Debug, Eq, PartialEq, Default)] -pub struct BiKZGProverParam { - /// Parameters - pub powers_of_g: Vec, -} +// /// `BiKZGProverParam` is used to generate a proof +// #[derive(Clone, Debug, Eq, PartialEq, Default)] +// pub struct BiKZGProverParam { +// /// Parameters +// pub powers_of_g: Vec, +// } /// `UnivariateVerifierParam` is used to check evaluation proofs for a given /// commitment. @@ -56,6 +56,17 @@ pub struct BiKZGProof { pub pi1: E::G1Affine, } +impl From> for BiKZGVerifierParam { + fn from(srs: BiKZGSRS) -> Self { + Self { + g: srs.powers_of_g[0], + h: srs.h, + tau_0_h: srs.tau_0_h, + tau_1_h: srs.tau_1_h, + } + } +} + impl SerdeObject for BiKZGCommitment { /// The purpose of unchecked functions is to read the internal memory representation /// of a type from bytes as quickly as possible. No sanitization checks are performed From c9c9a63aaa1b2e4c638332be4fe87107c729f64f Mon Sep 17 00:00:00 2001 From: zhenfei Date: Sun, 9 Jun 2024 23:37:46 -0400 Subject: [PATCH 06/31] wip --- bi-kzg/src/bi_kzg.rs | 26 ++++++++++++++++---- bi-kzg/src/lib.rs | 2 ++ bi-kzg/src/msm.rs | 16 +++++++++---- bi-kzg/src/pcs.rs | 2 +- bi-kzg/src/poly.rs | 56 +++++++++++++++++++++++++++++++++++++++++++ bi-kzg/src/structs.rs | 11 +++++++++ 6 files changed, 103 insertions(+), 10 deletions(-) create mode 100644 bi-kzg/src/poly.rs diff --git a/bi-kzg/src/bi_kzg.rs b/bi-kzg/src/bi_kzg.rs index 4b42ba0d..81495153 100644 --- a/bi-kzg/src/bi_kzg.rs +++ b/bi-kzg/src/bi_kzg.rs @@ -15,6 +15,7 @@ use rand::Rng; use rand::RngCore; use crate::msm::best_multiexp; +use crate::structs::BivaraitePolynomial; use crate::util::lagrange_coefficients; use crate::util::parallelize; use crate::{ @@ -29,16 +30,16 @@ pub struct BiKZG { impl PolynomialCommitmentScheme for BiKZG where - E::G1Affine: Add, + E::G1Affine: Add, { type SRS = BiKZGSRS; type ProverParam = BiKZGSRS; type VerifierParam = BiKZGVerifierParam; - type Polynomial = Vec; + type Polynomial = BivaraitePolynomial; type Commitment = BiKZGCommitment; type Proof = BiKZGProof; type Evaluation = E::Fr; - type Point = E::Fr; + type Point = (E::Fr, E::Fr); type BatchProof = Vec; fn gen_srs_for_testing( @@ -107,6 +108,8 @@ where }; BiKZGSRS { + tau_0, + tau_1, powers_of_g: affine_bases, h: E::G2Affine::generator(), tau_0_h: (E::G2Affine::generator() * tau_0).into(), @@ -127,7 +130,11 @@ where poly: &Self::Polynomial, ) -> Self::Commitment { Self::Commitment { - com: best_multiexp(poly, prover_param.borrow().powers_of_g.as_slice()).into(), + com: best_multiexp( + &poly.coefficients, + prover_param.borrow().powers_of_g.as_slice(), + ) + .into(), } } @@ -136,7 +143,16 @@ where polynomial: &Self::Polynomial, point: &Self::Point, ) -> (Self::Proof, Self::Evaluation) { - unimplemented!() + // fixme + let eval = polynomial.evaluate(&point.0, &point.1); + let q_0 = polynomial.evaluate(&prover_param.borrow().tau_0, &point.1); + let q_1 = polynomial.evaluate(&point.0, &prover_param.borrow().tau_1); + let proof = BiKZGProof { + pi0: (prover_param.borrow().powers_of_g[0] * q_0).into(), + pi1: (prover_param.borrow().powers_of_g[0] * q_1).into(), + }; + + (proof, eval) } fn verify( diff --git a/bi-kzg/src/lib.rs b/bi-kzg/src/lib.rs index 03f8ccd3..ff74f138 100644 --- a/bi-kzg/src/lib.rs +++ b/bi-kzg/src/lib.rs @@ -1,9 +1,11 @@ mod bi_kzg; mod msm; mod pcs; +mod poly; mod structs; #[cfg(test)] mod tests; mod util; +pub use structs::BivaraitePolynomial; pub use structs::{BiKZGCommitment, BiKZGProof, BiKZGSRS, BiKZGVerifierParam}; diff --git a/bi-kzg/src/msm.rs b/bi-kzg/src/msm.rs index 1836be13..79d56f15 100644 --- a/bi-kzg/src/msm.rs +++ b/bi-kzg/src/msm.rs @@ -4,7 +4,8 @@ use std::ops::{Add, Neg}; use halo2curves::ff::PrimeField; -use halo2curves::pairing::PairingCurveAffine;use halo2curves::group::Group; +use halo2curves::group::Group; +use halo2curves::pairing::PairingCurveAffine; fn get_booth_index(window_index: usize, window_size: usize, el: &[u8]) -> i32 { // Booth encoding: @@ -55,7 +56,10 @@ fn get_booth_index(window_index: usize, window_size: usize, el: &[u8]) -> i32 { /// This function will panic if coeffs and bases have a different length. /// /// This will use multithreading if beneficial. -pub fn best_multiexp>(coeffs: &[C::Scalar], bases: &[C]) -> C::Curve { +pub fn best_multiexp>( + coeffs: &[C::Scalar], + bases: &[C], +) -> C::Curve { assert_eq!(coeffs.len(), bases.len()); let num_threads = rayon::current_num_threads(); @@ -84,7 +88,11 @@ pub fn best_multiexp>(coeffs: &[C::S } } -pub fn multiexp_serial>(coeffs: &[C::Scalar], bases: &[C], acc: &mut C::Curve) { +pub fn multiexp_serial>( + coeffs: &[C::Scalar], + bases: &[C], + acc: &mut C::Curve, +) { let coeffs: Vec<_> = coeffs.iter().map(|a| a.to_repr()).collect(); let c = if bases.len() < 4 { @@ -109,7 +117,7 @@ pub fn multiexp_serial>(coeffs: &[C: Projective(C::Curve), } - impl> Bucket { + impl> Bucket { fn add_assign(&mut self, other: &C) { *self = match *self { Bucket::None => Bucket::Affine(*other), diff --git a/bi-kzg/src/pcs.rs b/bi-kzg/src/pcs.rs index a2e8afc0..a257491a 100644 --- a/bi-kzg/src/pcs.rs +++ b/bi-kzg/src/pcs.rs @@ -15,7 +15,7 @@ pub trait PolynomialCommitmentScheme { /// Structured reference string type SRS: Clone + Debug; /// Polynomial and its associated types - type Polynomial: Clone + Debug + PartialEq + Eq; + type Polynomial: Clone + Debug; /// Polynomial input domain type Point: Clone + Debug + Sync + PartialEq + Eq; /// Polynomial Evaluation diff --git a/bi-kzg/src/poly.rs b/bi-kzg/src/poly.rs new file mode 100644 index 00000000..6201ab34 --- /dev/null +++ b/bi-kzg/src/poly.rs @@ -0,0 +1,56 @@ +use halo2curves::ff::Field; +use halo2curves::pairing::Engine; + +use crate::structs::BivaraitePolynomial; + +impl BivaraitePolynomial { + pub fn new(coefficients: Vec, degree_0: usize, degree_1: usize) -> Self { + assert_eq!(coefficients.len(), (degree_0 + 1) * (degree_1 + 1)); + Self { + coefficients, + degree_0, + degree_1, + } + } + + pub fn evaluate(&self, x: &F, y: &F) -> F { + let mut result = F::ZERO; + let mut x_power = F::ONE; + for i in 0..=self.degree_0 { + let mut y_power = F::ONE; + for j in 0..=self.degree_1 { + result += self.coefficients[i * (self.degree_1 + 1) + j] * x_power * y_power; + y_power *= y; + } + x_power *= x; + } + result + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_bivariate_poly_eval() { + use crate::structs::BivaraitePolynomial; + use halo2curves::bn256::Fr; + + let poly = BivaraitePolynomial::new( + vec![ + Fr::from(1u64), + Fr::from(2u64), + Fr::from(3u64), + Fr::from(4u64), + ], + 1, + 1, + ); + let x = Fr::from(5u64); + let y = Fr::from(6u64); + let result = poly.evaluate(&x, &y); + assert_eq!( + result, + Fr::from(1u64) + Fr::from(2u64) * x + Fr::from(3u64) * y + Fr::from(4u64) * x * y + ); + } +} diff --git a/bi-kzg/src/structs.rs b/bi-kzg/src/structs.rs index 24368ba7..bd36ff8c 100644 --- a/bi-kzg/src/structs.rs +++ b/bi-kzg/src/structs.rs @@ -2,9 +2,20 @@ use std::io::{self, Read, Write}; use halo2curves::{pairing::Engine, serde::SerdeObject}; +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct BivaraitePolynomial { + pub coefficients: Vec, + pub degree_0: usize, + pub degree_1: usize, +} + /// Structured reference string for Bi-KZG polynomial commitment scheme. #[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct BiKZGSRS { + // FIXME: remove me + pub tau_0: E::Fr, + pub tau_1: E::Fr, + /// (g_1^{\tau_0^i\tau_1^j})_{i\in [0,N], j\in [0, M]} = \\ /// ( /// g_1, g_1^{\tau_0}, g_1^{\tau_0^2}, ..., g_1^{\tau_0^N}, From 20c860f50c98649061f4160c3e6a414a1f6645cb Mon Sep 17 00:00:00 2001 From: zhenfei Date: Mon, 10 Jun 2024 09:44:35 -0400 Subject: [PATCH 07/31] wip --- bi-kzg/src/bi_kzg.rs | 39 ++++++++++++---- bi-kzg/src/poly.rs | 108 +++++++++++++++++++++++++++++++++++-------- bi-kzg/src/tests.rs | 38 +++++++++++++-- bi-kzg/src/util.rs | 4 +- 4 files changed, 155 insertions(+), 34 deletions(-) diff --git a/bi-kzg/src/bi_kzg.rs b/bi-kzg/src/bi_kzg.rs index 81495153..d7d6cc6c 100644 --- a/bi-kzg/src/bi_kzg.rs +++ b/bi-kzg/src/bi_kzg.rs @@ -9,7 +9,7 @@ use halo2curves::group::Curve; use halo2curves::group::Group; // use halo2curves::msm::best_multiexp; -use halo2curves::pairing::Engine; +use halo2curves::pairing::{MillerLoopResult, MultiMillerLoop}; use halo2curves::CurveAffine; use rand::Rng; use rand::RngCore; @@ -24,11 +24,11 @@ use crate::{ BiKZGCommitment, BiKZGProof, BiKZGSRS, BiKZGVerifierParam, }; -pub struct BiKZG { - _engine: PhantomData, +pub struct BiKZG { + _MultiMillerLoop: PhantomData, } -impl PolynomialCommitmentScheme for BiKZG +impl PolynomialCommitmentScheme for BiKZG where E::G1Affine: Add, { @@ -77,11 +77,11 @@ where println!("start to compute the scalars"); // computes the vector of L_i^N(tau_0) * L_j^M(tau_1) for i in 0..supported_n and j in 0..supported_m let scalars = { - let powers_of_omega_0 = powers_of_field_elements(omega_0, supported_n); - let powers_of_tau_0 = powers_of_field_elements(tau_0, supported_n); + let powers_of_omega_0 = powers_of_field_elements(&omega_0, supported_n); + let powers_of_tau_0 = powers_of_field_elements(&tau_0, supported_n); let lagrange_tau_0 = lagrange_coefficients(&powers_of_omega_0, &powers_of_tau_0); - let powers_of_omega_1 = powers_of_field_elements(omega_1, supported_m); - let powers_of_tau_1 = powers_of_field_elements(tau_1, supported_m); + let powers_of_omega_1 = powers_of_field_elements(&omega_1, supported_m); + let powers_of_tau_1 = powers_of_field_elements(&tau_1, supported_m); let lagrange_tau_1 = lagrange_coefficients(&powers_of_omega_1, &powers_of_tau_1); tensor_product_parallel(&lagrange_tau_0, &lagrange_tau_1) }; @@ -161,8 +161,27 @@ where point: &Self::Point, value: &Self::Evaluation, proof: &Self::Proof, - ) -> bool { - unimplemented!() + ) -> bool + where + E: MultiMillerLoop, + { + let pi0_a_pi1_b_g1_cmu = best_multiexp( + &[point.0, point.1, E::Fr::ONE, -*value], + &[ + proof.pi0, + proof.pi1, + commitment.com.into(), + verifier_param.g.into(), + ], + ); + let pi0_a_pi1_b_g1_cmu = (-pi0_a_pi1_b_g1_cmu).to_affine(); + let res = E::multi_miller_loop(&[ + (&proof.pi0, &verifier_param.tau_0_h.into()), + (&proof.pi1, &verifier_param.tau_1_h.into()), + (&pi0_a_pi1_b_g1_cmu, &verifier_param.h.into()), + ]); + + res.final_exponentiation().is_identity().into() } fn multi_open( diff --git a/bi-kzg/src/poly.rs b/bi-kzg/src/poly.rs index 6201ab34..944e1789 100644 --- a/bi-kzg/src/poly.rs +++ b/bi-kzg/src/poly.rs @@ -1,31 +1,44 @@ use halo2curves::ff::Field; -use halo2curves::pairing::Engine; +use rand::RngCore; use crate::structs::BivaraitePolynomial; +use crate::util::powers_of_field_elements; impl BivaraitePolynomial { + #[inline] pub fn new(coefficients: Vec, degree_0: usize, degree_1: usize) -> Self { - assert_eq!(coefficients.len(), (degree_0 + 1) * (degree_1 + 1)); + assert_eq!(coefficients.len(), degree_0 * degree_1); Self { coefficients, degree_0, degree_1, } } + + pub fn random(mut rng: impl RngCore, degree_0: usize, degree_1: usize) -> Self { + let coefficients = (0..degree_0 * degree_1) + .map(|_| F::random(&mut rng)) + .collect(); + Self::new(coefficients, degree_0, degree_1) + } pub fn evaluate(&self, x: &F, y: &F) -> F { - let mut result = F::ZERO; - let mut x_power = F::ONE; - for i in 0..=self.degree_0 { - let mut y_power = F::ONE; - for j in 0..=self.degree_1 { - result += self.coefficients[i * (self.degree_1 + 1) + j] * x_power * y_power; - y_power *= y; - } - x_power *= x; - } - result + let x_power = powers_of_field_elements(x, self.degree_0); + let y_power = powers_of_field_elements(y, self.degree_1); + + self.coefficients + .chunks_exact(self.degree_0) + .zip(y_power.iter()) + .fold(F::ZERO, |acc, (chunk, y_i)| { + acc + chunk + .iter() + .zip(x_power.iter()) + .fold(F::ZERO, |acc, (c, x_i)| acc + *c * *x_i) + * y_i + }) } + + } #[cfg(test)] @@ -34,6 +47,53 @@ mod tests { fn test_bivariate_poly_eval() { use crate::structs::BivaraitePolynomial; use halo2curves::bn256::Fr; + { + let poly = BivaraitePolynomial::new( + vec![ + Fr::from(1u64), + Fr::from(2u64), + Fr::from(3u64), + Fr::from(4u64), + ], + 2, + 2, + ); + let x = Fr::from(5u64); + let y = Fr::from(7u64); + let result = poly.evaluate(&x, &y); + assert_eq!( + result, + Fr::from(1u64) + Fr::from(2u64) * x + Fr::from(3u64) * y + Fr::from(4u64) * x * y + ); + } + + { + let poly = BivaraitePolynomial::new( + vec![ + Fr::from(1u64), + Fr::from(2u64), + Fr::from(3u64), + Fr::from(4u64), + Fr::from(5u64), + Fr::from(6u64), + Fr::from(7u64), + Fr::from(8u64), + ], + 2, + 4, + ); + let x = Fr::from(9u64); + let y = Fr::from(10u64); + let result = poly.evaluate(&x, &y); + assert_eq!( + result, + Fr::from(1u64) + + Fr::from(2u64) * x + + (Fr::from(3u64) + Fr::from(4u64) * x) * y + + (Fr::from(5u64) + Fr::from(6u64) * x) * y * y + + (Fr::from(7u64) + Fr::from(8u64) * x) * y * y * y + ); + } let poly = BivaraitePolynomial::new( vec![ @@ -41,16 +101,28 @@ mod tests { Fr::from(2u64), Fr::from(3u64), Fr::from(4u64), + Fr::from(5u64), + Fr::from(6u64), + Fr::from(7u64), + Fr::from(8u64), ], - 1, - 1, + 4, + 2, ); - let x = Fr::from(5u64); - let y = Fr::from(6u64); + let x = Fr::from(9u64); + let y = Fr::from(10u64); let result = poly.evaluate(&x, &y); assert_eq!( result, - Fr::from(1u64) + Fr::from(2u64) * x + Fr::from(3u64) * y + Fr::from(4u64) * x * y + Fr::from(1u64) + + Fr::from(2u64) * x + + Fr::from(3u64) * x * x + + Fr::from(4u64) * x * x * x + + (Fr::from(5u64) + + Fr::from(6u64) * x + + Fr::from(7u64) * x * x + + Fr::from(8u64) * x * x * x) + * y ); } } diff --git a/bi-kzg/src/tests.rs b/bi-kzg/src/tests.rs index 5900fbe6..25a2887b 100644 --- a/bi-kzg/src/tests.rs +++ b/bi-kzg/src/tests.rs @@ -1,14 +1,44 @@ use ark_std::test_rng; -use halo2curves::bn256::Bn256; +use halo2curves::bn256::{Bn256, Fr}; -use crate::{bi_kzg::BiKZG, pcs::PolynomialCommitmentScheme}; +use crate::{bi_kzg::BiKZG, pcs::PolynomialCommitmentScheme, BivaraitePolynomial}; #[test] fn test_bi_kzg_e2e() { let mut rng = test_rng(); - let n = 4; - let m = 8; + let n = 2; + let m = 4; let srs = BiKZG::::gen_srs_for_testing(&mut rng, n, m); + let poly = BivaraitePolynomial::new( + vec![ + Fr::from(1u64), + Fr::from(2u64), + Fr::from(3u64), + Fr::from(4u64), + Fr::from(5u64), + Fr::from(6u64), + Fr::from(7u64), + Fr::from(8u64), + ], + n, + m, + ); + // let poly = BivaraitePolynomial::random(&mut rng, n, m); + + let x = Fr::from(5u64); + let y = Fr::from(6u64); + + let commit = BiKZG::::commit(&srs, &poly); + let (proof, eval) = BiKZG::::open(&srs, &poly, &(x, y)); + + assert!(BiKZG::::verify( + &srs.into(), + &commit, + &(x, y), + &eval, + &proof + )); + assert!(false) } diff --git a/bi-kzg/src/util.rs b/bi-kzg/src/util.rs index 9c92b467..2491499a 100644 --- a/bi-kzg/src/util.rs +++ b/bi-kzg/src/util.rs @@ -1,9 +1,9 @@ use halo2curves::ff::Field; use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; -pub(crate) fn powers_of_field_elements(x: F, n: usize) -> Vec { +pub(crate) fn powers_of_field_elements(x: &F, n: usize) -> Vec { let mut powers = vec![F::ONE]; - let mut cur = x; + let mut cur = *x; for _ in 0..n - 1 { powers.push(cur); cur *= x; From ef78a91202d1c8c476f68d6ab545a7468233d662 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Mon, 10 Jun 2024 10:29:28 -0400 Subject: [PATCH 08/31] has error --- bi-kzg/src/bi_kzg.rs | 27 +++++++++++++++++++++++---- bi-kzg/src/poly.rs | 4 +--- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/bi-kzg/src/bi_kzg.rs b/bi-kzg/src/bi_kzg.rs index d7d6cc6c..81fd6f9c 100644 --- a/bi-kzg/src/bi_kzg.rs +++ b/bi-kzg/src/bi_kzg.rs @@ -144,15 +144,34 @@ where point: &Self::Point, ) -> (Self::Proof, Self::Evaluation) { // fixme - let eval = polynomial.evaluate(&point.0, &point.1); - let q_0 = polynomial.evaluate(&prover_param.borrow().tau_0, &point.1); - let q_1 = polynomial.evaluate(&point.0, &prover_param.borrow().tau_1); + let tau_0 = prover_param.borrow().tau_0; + let tau_1 = prover_param.borrow().tau_1; + let a = point.0; + let b = point.1; + + let u = polynomial.evaluate(&a, &b); + let u_prime = polynomial.evaluate(&tau_0, &b); + + let f_tau0_b = polynomial.evaluate(&tau_0, &b); + let f_a_tau1 = polynomial.evaluate(&a, &tau_1); + + let q_0 = (f_tau0_b - u) * ((tau_0 - a).invert().unwrap()); + let q_1 = (f_a_tau1 - u_prime) * ((tau_1 - b).invert().unwrap()); + let proof = BiKZGProof { pi0: (prover_param.borrow().powers_of_g[0] * q_0).into(), pi1: (prover_param.borrow().powers_of_g[0] * q_1).into(), }; - (proof, eval) + let c = polynomial.evaluate(&tau_0, &tau_1); + + let t0 = q_0 * (tau_0 - a); + let t1 = q_1 * (tau_1 - b); + let right = c - u; + + assert_eq!(t0 + t1, right, "t0 + t1 != right"); + + (proof, u) } fn verify( diff --git a/bi-kzg/src/poly.rs b/bi-kzg/src/poly.rs index 944e1789..f8c86d22 100644 --- a/bi-kzg/src/poly.rs +++ b/bi-kzg/src/poly.rs @@ -14,7 +14,7 @@ impl BivaraitePolynomial { degree_1, } } - + pub fn random(mut rng: impl RngCore, degree_0: usize, degree_1: usize) -> Self { let coefficients = (0..degree_0 * degree_1) .map(|_| F::random(&mut rng)) @@ -37,8 +37,6 @@ impl BivaraitePolynomial { * y_i }) } - - } #[cfg(test)] From e9efd14f43b27c116159894ef0202c96c18358a1 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Mon, 10 Jun 2024 10:35:09 -0400 Subject: [PATCH 09/31] fix error in equation --- bi-kzg/src/bi_kzg.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bi-kzg/src/bi_kzg.rs b/bi-kzg/src/bi_kzg.rs index 81fd6f9c..1c0731d7 100644 --- a/bi-kzg/src/bi_kzg.rs +++ b/bi-kzg/src/bi_kzg.rs @@ -148,6 +148,7 @@ where let tau_1 = prover_param.borrow().tau_1; let a = point.0; let b = point.1; + let c = polynomial.evaluate(&tau_0, &tau_1); let u = polynomial.evaluate(&a, &b); let u_prime = polynomial.evaluate(&tau_0, &b); @@ -156,14 +157,13 @@ where let f_a_tau1 = polynomial.evaluate(&a, &tau_1); let q_0 = (f_tau0_b - u) * ((tau_0 - a).invert().unwrap()); - let q_1 = (f_a_tau1 - u_prime) * ((tau_1 - b).invert().unwrap()); + let q_1 = (c - u_prime) * ((tau_1 - b).invert().unwrap()); let proof = BiKZGProof { pi0: (prover_param.borrow().powers_of_g[0] * q_0).into(), pi1: (prover_param.borrow().powers_of_g[0] * q_1).into(), }; - let c = polynomial.evaluate(&tau_0, &tau_1); let t0 = q_0 * (tau_0 - a); let t1 = q_1 * (tau_1 - b); From f0650e97e69fb6e2fe56acc896043a59c3d2e8c3 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Mon, 10 Jun 2024 10:55:59 -0400 Subject: [PATCH 10/31] done with coefficient form --- bi-kzg/src/bi_kzg.rs | 59 ++++++++++++++++++++++++++++++++++--------- bi-kzg/src/structs.rs | 2 ++ bi-kzg/src/util.rs | 24 ++++++++++++++++-- 3 files changed, 71 insertions(+), 14 deletions(-) diff --git a/bi-kzg/src/bi_kzg.rs b/bi-kzg/src/bi_kzg.rs index 1c0731d7..80bcc02b 100644 --- a/bi-kzg/src/bi_kzg.rs +++ b/bi-kzg/src/bi_kzg.rs @@ -10,6 +10,7 @@ use halo2curves::group::Group; // use halo2curves::msm::best_multiexp; use halo2curves::pairing::{MillerLoopResult, MultiMillerLoop}; +use halo2curves::pasta::pallas::Scalar; use halo2curves::CurveAffine; use rand::Rng; use rand::RngCore; @@ -76,18 +77,20 @@ where println!("start to compute the scalars"); // computes the vector of L_i^N(tau_0) * L_j^M(tau_1) for i in 0..supported_n and j in 0..supported_m - let scalars = { + let (scalars, lagrange_scalars) = { let powers_of_omega_0 = powers_of_field_elements(&omega_0, supported_n); let powers_of_tau_0 = powers_of_field_elements(&tau_0, supported_n); let lagrange_tau_0 = lagrange_coefficients(&powers_of_omega_0, &powers_of_tau_0); let powers_of_omega_1 = powers_of_field_elements(&omega_1, supported_m); let powers_of_tau_1 = powers_of_field_elements(&tau_1, supported_m); let lagrange_tau_1 = lagrange_coefficients(&powers_of_omega_1, &powers_of_tau_1); - tensor_product_parallel(&lagrange_tau_0, &lagrange_tau_1) + let scalars = tensor_product_parallel(&powers_of_tau_0, &powers_of_tau_1); + let largrange_scalars = tensor_product_parallel(&lagrange_tau_0, &lagrange_tau_1); + (scalars, largrange_scalars) }; println!("start to compute the affine bases"); - let affine_bases = { + let coeff_bases = { let mut proj_bases = vec![E::G1::identity(); supported_n * supported_m]; parallelize(&mut proj_bases, |g, start| { for (idx, g) in g.iter_mut().enumerate() { @@ -96,6 +99,28 @@ where } }); + let mut g_bases = vec![E::G1Affine::identity(); supported_n * supported_m]; + parallelize(&mut g_bases, |g, starts| { + E::G1::batch_normalize( + &proj_bases[starts..(starts + g.len())], + g, + ); + }); + drop(proj_bases); + g_bases + }; + + + println!("start to compute the lagrange bases"); + let largrange_bases = { + let mut proj_bases = vec![E::G1::identity(); supported_n * supported_m]; + parallelize(&mut proj_bases, |g, start| { + for (idx, g) in g.iter_mut().enumerate() { + let offset = start + idx; + *g = g1 * lagrange_scalars[offset]; + } + }); + let mut g_lagrange = vec![E::G1Affine::identity(); supported_n * supported_m]; parallelize(&mut g_lagrange, |g_lagrange, starts| { E::G1::batch_normalize( @@ -110,7 +135,8 @@ where BiKZGSRS { tau_0, tau_1, - powers_of_g: affine_bases, + powers_of_g: coeff_bases, + powers_of_g_largrange: largrange_bases, h: E::G2Affine::generator(), tau_0_h: (E::G2Affine::generator() * tau_0).into(), tau_1_h: (E::G2Affine::generator() * tau_1).into(), @@ -129,13 +155,21 @@ where prover_param: impl Borrow, poly: &Self::Polynomial, ) -> Self::Commitment { - Self::Commitment { - com: best_multiexp( - &poly.coefficients, - prover_param.borrow().powers_of_g.as_slice(), - ) + let com = best_multiexp( + &poly.coefficients, + prover_param.borrow().powers_of_g.as_slice(), + ) + .into(); + + assert_eq!( + com, + (prover_param.borrow().powers_of_g[0] + * poly.evaluate(&prover_param.borrow().tau_0, &prover_param.borrow().tau_1)) .into(), - } + "commitment is not equal to evaluation" + ); + + Self::Commitment { com } } fn open( @@ -164,7 +198,6 @@ where pi1: (prover_param.borrow().powers_of_g[0] * q_1).into(), }; - let t0 = q_0 * (tau_0 - a); let t1 = q_1 * (tau_1 - b); let right = c - u; @@ -199,8 +232,10 @@ where (&proof.pi1, &verifier_param.tau_1_h.into()), (&pi0_a_pi1_b_g1_cmu, &verifier_param.h.into()), ]); + let res = res.final_exponentiation().is_identity().into(); - res.final_exponentiation().is_identity().into() + println!("res: {:?}", res); + res } fn multi_open( diff --git a/bi-kzg/src/structs.rs b/bi-kzg/src/structs.rs index bd36ff8c..4d1163d9 100644 --- a/bi-kzg/src/structs.rs +++ b/bi-kzg/src/structs.rs @@ -23,6 +23,8 @@ pub struct BiKZGSRS { /// ..., g_1^{\tau_0^N\tau_1^M} /// ) pub powers_of_g: Vec, + /// g in lagrange form + pub powers_of_g_largrange: Vec, /// The generator of G2. pub h: E::G2Affine, /// tau_0 times the above generator of G2. diff --git a/bi-kzg/src/util.rs b/bi-kzg/src/util.rs index 2491499a..8794455c 100644 --- a/bi-kzg/src/util.rs +++ b/bi-kzg/src/util.rs @@ -12,8 +12,8 @@ pub(crate) fn powers_of_field_elements(x: &F, n: usize) -> Vec { } pub(crate) fn tensor_product_parallel(vec1: &[F], vec2: &[F]) -> Vec { - vec1.par_iter() - .flat_map(|&i| vec2.iter().map(|&j| i * j).collect::>()) + vec2.par_iter() + .flat_map(|&i| vec1.iter().map(|&j| i * j).collect::>()) .collect() } @@ -82,3 +82,23 @@ fn test_lagrange_eval() { assert_eq!(result[1], -Fr::from(8u64)); assert_eq!(result[2], Fr::from(10u64)); } + + +#[test] +fn test_tensor_product(){ + use halo2curves::bn256::Fr; + let vec1 = vec![Fr::from(1u64), Fr::from(2u64), Fr::from(3u64)]; + let vec2 = vec![Fr::from(4u64), Fr::from(5u64), Fr::from(6u64)]; + let result = tensor_product_parallel(&vec1, &vec2); + assert_eq!(result[0], Fr::from(4u64)); + assert_eq!(result[1], Fr::from(2u64)*Fr::from(4u64)); + assert_eq!(result[2], Fr::from(3u64)*Fr::from(4u64)); + assert_eq!(result[3], Fr::from(5u64)); + assert_eq!(result[4], Fr::from(2u64)*Fr::from(5u64)); + assert_eq!(result[5], Fr::from(3u64)*Fr::from(5u64)); + assert_eq!(result[6], Fr::from(6u64)); + assert_eq!(result[7], Fr::from(2u64)*Fr::from(6u64)); + assert_eq!(result[8], Fr::from(3u64)*Fr::from(6u64)); +} + + From d15058a96578483ccd88dc41f24c5447e1fcb0f8 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Tue, 11 Jun 2024 20:59:00 -0400 Subject: [PATCH 11/31] wip --- bi-kzg/src/bi_kzg.rs | 33 +++++++---- bi-kzg/src/lib.rs | 3 +- bi-kzg/src/pcs.rs | 39 ------------- bi-kzg/src/poly.rs | 132 +++++++++++++++++++++++++++++++++++++++--- bi-kzg/src/structs.rs | 11 +++- bi-kzg/src/tests.rs | 55 +++++++++++++++++- bi-kzg/src/util.rs | 52 ----------------- 7 files changed, 209 insertions(+), 116 deletions(-) diff --git a/bi-kzg/src/bi_kzg.rs b/bi-kzg/src/bi_kzg.rs index 80bcc02b..7c881a85 100644 --- a/bi-kzg/src/bi_kzg.rs +++ b/bi-kzg/src/bi_kzg.rs @@ -16,8 +16,8 @@ use rand::Rng; use rand::RngCore; use crate::msm::best_multiexp; -use crate::structs::BivaraitePolynomial; -use crate::util::lagrange_coefficients; +use crate::poly::lagrange_coefficients; +use crate::structs::BivariatePolynomial; use crate::util::parallelize; use crate::{ pcs::PolynomialCommitmentScheme, @@ -26,7 +26,7 @@ use crate::{ }; pub struct BiKZG { - _MultiMillerLoop: PhantomData, + _phantom: PhantomData, } impl PolynomialCommitmentScheme for BiKZG @@ -36,7 +36,7 @@ where type SRS = BiKZGSRS; type ProverParam = BiKZGSRS; type VerifierParam = BiKZGVerifierParam; - type Polynomial = BivaraitePolynomial; + type Polynomial = BivariatePolynomial; type Commitment = BiKZGCommitment; type Proof = BiKZGProof; type Evaluation = E::Fr; @@ -64,6 +64,9 @@ where let omega_0 = omega.pow_vartime(&[(1 << E::Fr::S) / supported_n as u64]); let omega_1 = omega.pow_vartime(&[(1 << E::Fr::S) / supported_m as u64]); + println!("omega 0: {:?}", omega_0); + println!("omega 1: {:?}", omega_1); + assert!( omega_0.pow_vartime(&[supported_n as u64]) == E::Fr::ONE, "omega_0 is not root of unity for supported_n" @@ -101,18 +104,15 @@ where let mut g_bases = vec![E::G1Affine::identity(); supported_n * supported_m]; parallelize(&mut g_bases, |g, starts| { - E::G1::batch_normalize( - &proj_bases[starts..(starts + g.len())], - g, - ); + E::G1::batch_normalize(&proj_bases[starts..(starts + g.len())], g); }); drop(proj_bases); g_bases }; - println!("start to compute the lagrange bases"); - let largrange_bases = { + println!("lagrange scalars: {:?} ", lagrange_scalars); + let lagrange_bases = { let mut proj_bases = vec![E::G1::identity(); supported_n * supported_m]; parallelize(&mut proj_bases, |g, start| { for (idx, g) in g.iter_mut().enumerate() { @@ -136,7 +136,7 @@ where tau_0, tau_1, powers_of_g: coeff_bases, - powers_of_g_largrange: largrange_bases, + powers_of_g_lagrange: lagrange_bases, h: E::G2Affine::generator(), tau_0_h: (E::G2Affine::generator() * tau_0).into(), tau_1_h: (E::G2Affine::generator() * tau_1).into(), @@ -169,6 +169,17 @@ where "commitment is not equal to evaluation" ); + let lag_coeff = poly.lagrange_coeffs(); + let com_lag = best_multiexp( + &lag_coeff, + prover_param.borrow().powers_of_g_lagrange.as_slice(), + ) + .into(); + assert_eq!( + com, com_lag, + "commitment is not equal to lagrange commitment" + ); + Self::Commitment { com } } diff --git a/bi-kzg/src/lib.rs b/bi-kzg/src/lib.rs index ff74f138..4d557237 100644 --- a/bi-kzg/src/lib.rs +++ b/bi-kzg/src/lib.rs @@ -7,5 +7,6 @@ mod structs; mod tests; mod util; -pub use structs::BivaraitePolynomial; +pub use pcs::PolynomialCommitmentScheme; +pub use structs::BivariatePolynomial; pub use structs::{BiKZGCommitment, BiKZGProof, BiKZGSRS, BiKZGVerifierParam}; diff --git a/bi-kzg/src/pcs.rs b/bi-kzg/src/pcs.rs index a257491a..4a3fee9d 100644 --- a/bi-kzg/src/pcs.rs +++ b/bi-kzg/src/pcs.rs @@ -29,9 +29,6 @@ pub trait PolynomialCommitmentScheme { /// Build SRS for testing. /// - /// - For univariate polynomials, `supported_size` is the maximum degree. - /// - For multilinear polynomials, `supported_size` is the number of - /// variables. /// /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY. /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION. @@ -113,39 +110,3 @@ pub trait PolynomialCommitmentScheme { unimplemented!() } } - -// /// API definitions for structured reference string -// /// -// /// Credit: https://github.com/EspressoSystems/hyperplonk/blob/8698369edfe82bd6617a9609602380f21cabd1da/subroutines/src/pcs/mod.rs#L135 -// pub trait StructuredReferenceString: Sized { -// /// Prover parameters -// type ProverParam; -// /// Verifier parameters -// type VerifierParam; - -// /// Extract the prover parameters from the public parameters. -// fn extract_prover_param(&self, supported_size: usize) -> Self::ProverParam; -// /// Extract the verifier parameters from the public parameters. -// fn extract_verifier_param(&self, supported_size: usize) -> Self::VerifierParam; - -// /// Trim the universal parameters to specialize the public parameters -// /// for polynomials to the given `supported_size`, and -// /// returns committer key and verifier key. -// /// -// /// - For univariate polynomials, `supported_size` is the maximum degree. -// /// - For multilinear polynomials, `supported_size` is 2 to the number of -// /// variables. -// /// -// /// `supported_log_size` should be in range `1..=params.log_size` -// fn trim(&self, supported_size: usize) -> (Self::ProverParam, Self::VerifierParam); - -// /// Build SRS for testing. -// /// -// /// - For univariate polynomials, `supported_size` is the maximum degree. -// /// - For multilinear polynomials, `supported_size` is the number of -// /// variables. -// /// -// /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY. -// /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION. -// fn gen_srs_for_testing(rng: &mut R, supported_size: usize) -> Self; -// } diff --git a/bi-kzg/src/poly.rs b/bi-kzg/src/poly.rs index f8c86d22..b00845f1 100644 --- a/bi-kzg/src/poly.rs +++ b/bi-kzg/src/poly.rs @@ -1,10 +1,11 @@ -use halo2curves::ff::Field; +use halo2curves::ff::{Field, PrimeField}; use rand::RngCore; +use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; -use crate::structs::BivaraitePolynomial; +use crate::structs::{BivariateLagrangePolynomial, BivariatePolynomial}; use crate::util::powers_of_field_elements; -impl BivaraitePolynomial { +impl BivariatePolynomial { #[inline] pub fn new(coefficients: Vec, degree_0: usize, degree_1: usize) -> Self { assert_eq!(coefficients.len(), degree_0 * degree_1); @@ -37,16 +38,105 @@ impl BivaraitePolynomial { * y_i }) } + + /// + pub fn lagrange_coeffs(&self) -> Vec { + // roots of unity for supported_n and supported_m + let (omega_0, omega_1) = { + let omega = F::ROOT_OF_UNITY; + let omega_0 = omega.pow_vartime(&[(1 << F::S) / self.degree_0 as u64]); + let omega_1 = omega.pow_vartime(&[(1 << F::S) / self.degree_1 as u64]); + + assert!( + omega_0.pow_vartime(&[self.degree_0 as u64]) == F::ONE, + "omega_0 is not root of unity for supported_n" + ); + assert!( + omega_1.pow_vartime(&[self.degree_1 as u64]) == F::ONE, + "omega_1 is not root of unity for supported_m" + ); + (omega_0, omega_1) + }; + let powers_of_omega_0 = powers_of_field_elements(&omega_0, self.degree_0); + let powers_of_omega_1 = powers_of_field_elements(&omega_1, self.degree_1); + println!( + "omega len {} {}", + powers_of_omega_0.len(), + powers_of_omega_1.len() + ); + + // Todo! Optimize me. This is not efficient. + let mut res = vec![]; + for omega_1_power in powers_of_omega_1.iter() { + for omega_0_power in powers_of_omega_0.iter() { + res.push(self.evaluate(omega_0_power, omega_1_power)); + } + } + + println!("res: {:?}", res); + res + } + + // pub fn from_lagrange_coeffs(coeffs: Vec, degree_0: usize, degree_1: usize) -> Self { + // assert_eq!(coeffs.len(), degree_0 * degree_1); + // todo!() + // } +} + +/// For x in points, compute the Lagrange coefficients at x given the roots. +/// `L_{i}(x) = \prod_{j \neq i} \frac{x - r_j}{r_i - r_j}`` +pub(crate) fn lagrange_coefficients(roots: &[F], points: &[F]) -> Vec { + roots + .par_iter() + .enumerate() + .map(|(i, _)| { + let mut numerator = F::ONE; + let mut denominator = F::ONE; + for j in 0..roots.len() { + if i == j { + continue; + } + numerator *= roots[j] - points[i]; + denominator *= roots[j] - roots[i]; + } + numerator * denominator.invert().unwrap() + }) + .collect() +} + +impl BivariateLagrangePolynomial { + fn new(coeffs: Vec, degree_0: usize, degree_1: usize) -> Self { + assert_eq!(coeffs.len(), degree_0 * degree_1); + Self { + coefficients: coeffs, + degree_0, + degree_1, + } + } +} + +impl From> for BivariateLagrangePolynomial { + fn from(poly: BivariatePolynomial) -> Self { + let coeffs = poly.lagrange_coeffs(); + BivariateLagrangePolynomial::new(coeffs, poly.degree_0, poly.degree_1) + } +} + +impl From> for BivariatePolynomial { + fn from(poly: BivariateLagrangePolynomial) -> Self { + todo!() + } } #[cfg(test)] mod tests { + use crate::structs::BivariatePolynomial; + use halo2curves::bn256::Fr; + #[test] fn test_bivariate_poly_eval() { - use crate::structs::BivaraitePolynomial; - use halo2curves::bn256::Fr; { - let poly = BivaraitePolynomial::new( + let poly = BivariatePolynomial::new( vec![ Fr::from(1u64), Fr::from(2u64), @@ -66,7 +156,7 @@ mod tests { } { - let poly = BivaraitePolynomial::new( + let poly = BivariatePolynomial::new( vec![ Fr::from(1u64), Fr::from(2u64), @@ -93,7 +183,7 @@ mod tests { ); } - let poly = BivaraitePolynomial::new( + let poly = BivariatePolynomial::new( vec![ Fr::from(1u64), Fr::from(2u64), @@ -123,4 +213,30 @@ mod tests { * y ); } + + // #[test] + // fn test_lagrange_coeffs() { + // let poly = BivariatePolynomial::new( + // vec![ + // Fr::from(1u64), + // Fr::from(2u64), + // Fr::from(3u64), + // Fr::from(4u64), + // Fr::from(5u64), + // Fr::from(10u64), + // Fr::from(15u64), + // Fr::from(20u64), + // ], + // 4, + // 2, + // ); + + // let lagrange_coeffs = poly.lagrange_coeffs(); + // println!("lag: {:?}", lagrange_coeffs); + // assert_eq!(lagrange_coeffs.len(), 8); + // assert_eq!(lagrange_coeffs[0], Fr::from(1u64)); + // assert_eq!(lagrange_coeffs[1], Fr::from(2u64)); + // assert_eq!(lagrange_coeffs[2], Fr::from(3u64)); + // assert_eq!(lagrange_coeffs[3], Fr::from(4u64)); + // } } diff --git a/bi-kzg/src/structs.rs b/bi-kzg/src/structs.rs index 4d1163d9..8d25f512 100644 --- a/bi-kzg/src/structs.rs +++ b/bi-kzg/src/structs.rs @@ -3,7 +3,14 @@ use std::io::{self, Read, Write}; use halo2curves::{pairing::Engine, serde::SerdeObject}; #[derive(Clone, Debug, Default, PartialEq, Eq)] -pub struct BivaraitePolynomial { +pub struct BivariatePolynomial { + pub coefficients: Vec, + pub degree_0: usize, + pub degree_1: usize, +} + +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct BivariateLagrangePolynomial { pub coefficients: Vec, pub degree_0: usize, pub degree_1: usize, @@ -24,7 +31,7 @@ pub struct BiKZGSRS { /// ) pub powers_of_g: Vec, /// g in lagrange form - pub powers_of_g_largrange: Vec, + pub powers_of_g_lagrange: Vec, /// The generator of G2. pub h: E::G2Affine, /// tau_0 times the above generator of G2. diff --git a/bi-kzg/src/tests.rs b/bi-kzg/src/tests.rs index 25a2887b..cbbf2ea1 100644 --- a/bi-kzg/src/tests.rs +++ b/bi-kzg/src/tests.rs @@ -1,7 +1,30 @@ use ark_std::test_rng; use halo2curves::bn256::{Bn256, Fr}; -use crate::{bi_kzg::BiKZG, pcs::PolynomialCommitmentScheme, BivaraitePolynomial}; +use crate::{ + bi_kzg::BiKZG, pcs::PolynomialCommitmentScheme, poly::lagrange_coefficients, + util::tensor_product_parallel, BivariatePolynomial, +}; + +// #[test] +// fn test_interpolation() { +// let f = (0..8).map(|x| Fr::from(x as u64)).collect::>(); +// let f = BivariatePolynomial::new(f, 2, 4); +// let r1 = (0..2).map(|x| Fr::from(x as u64)).collect::>(); +// let r2 = (0..4).map(|x| Fr::from(x as u64)).collect::>(); + +// let evals = r2 +// .iter() +// .flat_map(|r2| { +// r1.iter() +// .map(|&r1| f.evaluate(&r1, &r2)) +// .collect::>() +// }) +// .collect::>(); + +// let power + +// } #[test] fn test_bi_kzg_e2e() { @@ -10,7 +33,7 @@ fn test_bi_kzg_e2e() { let m = 4; let srs = BiKZG::::gen_srs_for_testing(&mut rng, n, m); - let poly = BivaraitePolynomial::new( + let poly = BivariatePolynomial::new( vec![ Fr::from(1u64), Fr::from(2u64), @@ -24,7 +47,7 @@ fn test_bi_kzg_e2e() { n, m, ); - // let poly = BivaraitePolynomial::random(&mut rng, n, m); + // let poly = BivariatePolynomial::random(&mut rng, n, m); let x = Fr::from(5u64); let y = Fr::from(6u64); @@ -42,3 +65,29 @@ fn test_bi_kzg_e2e() { assert!(false) } + +#[test] +fn test_lagrange_eval() { + let roots = vec![Fr::from(1u64), Fr::from(2u64), Fr::from(3u64)]; + let points = vec![Fr::from(4u64), Fr::from(5u64), Fr::from(6u64)]; + let result = lagrange_coefficients(&roots, &points); + assert_eq!(result[0], Fr::from(1u64)); + assert_eq!(result[1], -Fr::from(8u64)); + assert_eq!(result[2], Fr::from(10u64)); +} + +#[test] +fn test_tensor_product() { + let vec1 = vec![Fr::from(1u64), Fr::from(2u64), Fr::from(3u64)]; + let vec2 = vec![Fr::from(4u64), Fr::from(5u64), Fr::from(6u64)]; + let result = tensor_product_parallel(&vec1, &vec2); + assert_eq!(result[0], Fr::from(4u64)); + assert_eq!(result[1], Fr::from(2u64) * Fr::from(4u64)); + assert_eq!(result[2], Fr::from(3u64) * Fr::from(4u64)); + assert_eq!(result[3], Fr::from(5u64)); + assert_eq!(result[4], Fr::from(2u64) * Fr::from(5u64)); + assert_eq!(result[5], Fr::from(3u64) * Fr::from(5u64)); + assert_eq!(result[6], Fr::from(6u64)); + assert_eq!(result[7], Fr::from(2u64) * Fr::from(6u64)); + assert_eq!(result[8], Fr::from(3u64) * Fr::from(6u64)); +} diff --git a/bi-kzg/src/util.rs b/bi-kzg/src/util.rs index 8794455c..377a482b 100644 --- a/bi-kzg/src/util.rs +++ b/bi-kzg/src/util.rs @@ -17,27 +17,6 @@ pub(crate) fn tensor_product_parallel(vec1: &[F], vec2: &[F]) -> Vec(roots: &[F], points: &[F]) -> Vec { - roots - .par_iter() - .enumerate() - .map(|(i, _)| { - let mut numerator = F::ONE; - let mut denominator = F::ONE; - for j in 0..roots.len() { - if i == j { - continue; - } - numerator *= roots[j] - points[i]; - denominator *= roots[j] - roots[i]; - } - numerator * denominator.invert().unwrap() - }) - .collect() -} - /// This simple utility function will parallelize an operation that is to be /// performed over a mutable slice. /// credit: https://github.com/scroll-tech/halo2/blob/1070391642dd64b2d68b47ec246cba9e35bd3c15/halo2_proofs/src/arithmetic.rs#L546 @@ -71,34 +50,3 @@ pub(crate) fn parallelize_internal(v: &mut [T], f: F) { parallelize_internal(v, f); } - -#[test] -fn test_lagrange_eval() { - use halo2curves::bn256::Fr; - let roots = vec![Fr::from(1u64), Fr::from(2u64), Fr::from(3u64)]; - let points = vec![Fr::from(4u64), Fr::from(5u64), Fr::from(6u64)]; - let result = lagrange_coefficients(&roots, &points); - assert_eq!(result[0], Fr::from(1u64)); - assert_eq!(result[1], -Fr::from(8u64)); - assert_eq!(result[2], Fr::from(10u64)); -} - - -#[test] -fn test_tensor_product(){ - use halo2curves::bn256::Fr; - let vec1 = vec![Fr::from(1u64), Fr::from(2u64), Fr::from(3u64)]; - let vec2 = vec![Fr::from(4u64), Fr::from(5u64), Fr::from(6u64)]; - let result = tensor_product_parallel(&vec1, &vec2); - assert_eq!(result[0], Fr::from(4u64)); - assert_eq!(result[1], Fr::from(2u64)*Fr::from(4u64)); - assert_eq!(result[2], Fr::from(3u64)*Fr::from(4u64)); - assert_eq!(result[3], Fr::from(5u64)); - assert_eq!(result[4], Fr::from(2u64)*Fr::from(5u64)); - assert_eq!(result[5], Fr::from(3u64)*Fr::from(5u64)); - assert_eq!(result[6], Fr::from(6u64)); - assert_eq!(result[7], Fr::from(2u64)*Fr::from(6u64)); - assert_eq!(result[8], Fr::from(3u64)*Fr::from(6u64)); -} - - From 45e68fa903e03c37670f39d802fcd610c4f59931 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Thu, 13 Jun 2024 15:41:50 -0400 Subject: [PATCH 12/31] add benchmarks --- bi-kzg/Cargo.toml | 18 +++- bi-kzg/benches/bi_kzg_bench.rs | 156 +++++++++++++++++++++++++++++++++ bi-kzg/msm_bench.log | 148 +++++++++++++++++++++++++++++++ 3 files changed, 321 insertions(+), 1 deletion(-) create mode 100644 bi-kzg/benches/bi_kzg_bench.rs create mode 100644 bi-kzg/msm_bench.log diff --git a/bi-kzg/Cargo.toml b/bi-kzg/Cargo.toml index c9b640f8..c1ab6398 100644 --- a/bi-kzg/Cargo.toml +++ b/bi-kzg/Cargo.toml @@ -10,4 +10,20 @@ halo2curves.workspace = true log.workspace = true rand.workspace = true rayon.workspace = true -sha2.workspace = true \ No newline at end of file +sha2.workspace = true + +[dev-dependencies] +criterion.workspace = true +ark-bn254.workspace = true +ark-ec.workspace = true +ark-ff.workspace = true + +[[bench]] +name = "bi_kzg_bench" +harness = false + + +[features] +default = [ + "ark-ec/parallel", + ] \ No newline at end of file diff --git a/bi-kzg/benches/bi_kzg_bench.rs b/bi-kzg/benches/bi_kzg_bench.rs new file mode 100644 index 00000000..464e46b5 --- /dev/null +++ b/bi-kzg/benches/bi_kzg_bench.rs @@ -0,0 +1,156 @@ +use ark_bn254::{Fr, G1Affine, G1Projective}; +use ark_ec::short_weierstrass::Projective; +use ark_ec::Group; +use ark_ec::{AffineRepr, VariableBaseMSM}; +use ark_ff::Zero; +use ark_ff::{PrimeField, UniformRand}; +use halo2curves::bn256; +use halo2curves::ff::Field; +use halo2curves::msm::best_multiexp; +use rand::Rng; +use std::{thread, time::Duration}; + +use criterion::{black_box, criterion_group, criterion_main, Criterion}; + +fn criterion_benchmark(c: &mut Criterion) { + let degree_set = vec![2048, 4096, 8192, 16384]; + //let degree_set = vec![32786]; + // let mut res = vec![]; + for degree in degree_set { + let mut rng = rand::thread_rng(); + + let affine_bases = (0..degree) + .map(|_| G1Affine::rand(&mut rng)) + .collect::>(); + let proj_bases = affine_bases + .iter() + .map(|g| g.into_group()) + .collect::>(); + let scalars = (0..degree).map(|_| Fr::rand(&mut rng)).collect::>(); + + c.bench_function(&format!("arkworks MSM with degree {}", degree), |b| { + b.iter(|| { + _ = G1Projective::msm(&affine_bases, &scalars); + }); + }); + + let cpu_set = vec![4, 8, 16, 32]; + for nb_cpu in cpu_set.iter() { + c.bench_function( + &format!("custimzied MSM with degree {}, cpu={}", degree, nb_cpu), + |b| { + b.iter(|| { + _ = quick_exp(&proj_bases, &scalars, *nb_cpu); + }); + }, + ); + } + + let affine_bases = (0..degree) + .map(|_| bn256::G1Affine::random(&mut rng)) + .collect::>(); + + let scalars = (0..degree) + .map(|_| bn256::Fr::random(&mut rng)) + .collect::>(); + c.bench_function(&format!("halo2 MSM with degree {}", degree), |b| { + b.iter(|| { + _ = best_multiexp(&scalars, &affine_bases); + }); + }); + } +} + +criterion_group! { + name = benches; + config = Criterion::default().sample_size(10).measurement_time(Duration::from_secs(2)).warm_up_time(Duration::from_secs(1)); + targets = criterion_benchmark +} +criterion_main!(benches); + +pub fn quick_exp(points: &Vec, scalars: &Vec, num_cpu: usize) -> G1Projective { + let c = best_c(points.len(), num_cpu); + assert!(64 % c == 0); + + let mut result = G1Projective::zero(); + let nb_fr_bits = nb_fr_bits(); + + let point_len = points.len(); + let num_points_per_cpu = (point_len + num_cpu - 1) / num_cpu; + + let mut handles = vec![]; + + let point_ptr_usize = points.as_ptr() as usize; + let scalar_ptr_usize = scalars.as_ptr() as usize; + for i in 0..num_cpu { + let handle = thread::spawn(move || { + let mut bucket = vec![G1Projective::zero(); (nb_fr_bits / c) * (1 << c)]; + let start = i * num_points_per_cpu; + let end = std::cmp::min((i + 1) * num_points_per_cpu, point_len); + let point_ptr = point_ptr_usize as *const G1Projective; + let scalar_ptr = scalar_ptr_usize as *const Fr; + for j in start..end { + let point = unsafe { point_ptr.add(j).read() }; + let scalar_bigint = unsafe { scalar_ptr.add(j).read() }; + let limbs = scalar_bigint.into_bigint().0; + for k in 0..(nb_fr_bits / c) { + let mut temp = limbs[(k * c) / 64]; + let inside_idx = (k * c) % 64; + temp >>= inside_idx; + temp &= (1 << c) - 1; + bucket[(k << c) + temp as usize] += point; + } + } + let mut partial_sum = G1Projective::zero(); + for i in (0..(nb_fr_bits / c)).rev() { + for _ in 0..c { + partial_sum.double_in_place(); + } + let mut tmp = G1Projective::zero(); + for j in 0..(1 << c) { + let mut pow_res = G1Projective::zero(); + let mut base = bucket[(i << c) + j]; + for k in 0..c { + if (j >> k) & 1 == 1 { + pow_res += base; + } + base.double_in_place(); + } + tmp += pow_res; + } + partial_sum += tmp; + } + partial_sum + }); + handles.push(handle); + } + for handle in handles { + let partial_sum = handle.join().unwrap(); + result += partial_sum; + } + result +} + +#[inline] +fn nb_fr_bits() -> usize { + 256 +} + +#[inline] +fn cost_c(len: usize, c: usize, num_cpu: usize) -> usize { + let mut sum = 0_usize; + //first part + sum += (nb_fr_bits() / c) * len / num_cpu; + //second part + sum += nb_fr_bits() * (1 << c); + sum +} + +#[inline] +fn best_c(len: usize, num_cpu: usize) -> usize { + if cost_c(len, 8, num_cpu) > cost_c(len, 16, num_cpu) { + 16 + } else { + 8 + } +} diff --git a/bi-kzg/msm_bench.log b/bi-kzg/msm_bench.log new file mode 100644 index 00000000..7e53be81 --- /dev/null +++ b/bi-kzg/msm_bench.log @@ -0,0 +1,148 @@ + +running 4 tests +test poly::tests::test_bivariate_poly_eval ... ignored +test tests::test_bi_kzg_e2e ... ignored +test tests::test_lagrange_eval ... ignored +test tests::test_tensor_product ... ignored + +test result: ok. 0 passed; 0 failed; 4 ignored; 0 measured; 0 filtered out; finished in 0.00s + +arkworks MSM with degree 2048 + time: [1.8813 ms 1.9146 ms 1.9416 ms] + change: [+0.9709% +3.6059% +6.1557%] (p = 0.02 < 0.05) + Change within noise threshold. + +custimzied MSM with degree 2048, cpu=4 + time: [20.146 ms 20.382 ms 20.545 ms] + change: [+1.4738% +2.1380% +2.8502%] (p = 0.00 < 0.05) + Performance has regressed. + +custimzied MSM with degree 2048, cpu=8 + time: [14.017 ms 14.092 ms 14.181 ms] + change: [+1.1103% +1.5606% +2.1108%] (p = 0.00 < 0.05) + Performance has regressed. + +custimzied MSM with degree 2048, cpu=16 + time: [9.9906 ms 10.390 ms 10.934 ms] + change: [+0.8012% +7.7360% +14.804%] (p = 0.06 > 0.05) + No change in performance detected. + +custimzied MSM with degree 2048, cpu=32 + time: [9.2362 ms 9.6546 ms 10.492 ms] + change: [+2.9217% +7.4933% +14.080%] (p = 0.01 < 0.05) + Performance has regressed. +Found 1 outliers among 10 measurements (10.00%) + 1 (10.00%) high severe + +halo2 MSM with degree 2048 + time: [1.9300 ms 1.9571 ms 1.9810 ms] + change: [-3.9822% -1.4495% +0.8075%] (p = 0.30 > 0.05) + No change in performance detected. + +arkworks MSM with degree 4096 + time: [3.0241 ms 3.0370 ms 3.0486 ms] + change: [-0.5062% +0.9064% +2.7110%] (p = 0.30 > 0.05) + No change in performance detected. +Found 1 outliers among 10 measurements (10.00%) + 1 (10.00%) high severe + +custimzied MSM with degree 4096, cpu=4 + time: [26.259 ms 26.312 ms 26.380 ms] + change: [-0.5045% -0.0611% +0.3729%] (p = 0.80 > 0.05) + No change in performance detected. + +custimzied MSM with degree 4096, cpu=8 + time: [20.298 ms 20.364 ms 20.449 ms] + change: [+0.7966% +1.1451% +1.4964%] (p = 0.00 < 0.05) + Change within noise threshold. +Found 2 outliers among 10 measurements (20.00%) + 1 (10.00%) high mild + 1 (10.00%) high severe + +custimzied MSM with degree 4096, cpu=16 + time: [15.431 ms 15.823 ms 16.253 ms] + change: [+2.3820% +6.4428% +10.587%] (p = 0.01 < 0.05) + Performance has regressed. + +custimzied MSM with degree 4096, cpu=32 + time: [15.421 ms 15.668 ms 16.016 ms] + change: [+1.0481% +3.5925% +6.0496%] (p = 0.02 < 0.05) + Performance has regressed. + +halo2 MSM with degree 4096 + time: [3.2928 ms 3.3259 ms 3.3476 ms] + change: [+1.4265% +3.5407% +5.6867%] (p = 0.01 < 0.05) + Performance has regressed. +Found 2 outliers among 10 measurements (20.00%) + 2 (20.00%) high mild + +arkworks MSM with degree 8192 + time: [6.0368 ms 6.0925 ms 6.1836 ms] + change: [-0.1292% +0.8006% +1.7551%] (p = 0.13 > 0.05) + No change in performance detected. + +custimzied MSM with degree 8192, cpu=4 + time: [36.229 ms 36.595 ms 36.980 ms] + change: [-1.1925% -0.2872% +0.6541%] (p = 0.58 > 0.05) + No change in performance detected. +Found 1 outliers among 10 measurements (10.00%) + 1 (10.00%) high severe + +custimzied MSM with degree 8192, cpu=8 + time: [27.268 ms 27.671 ms 28.016 ms] + change: [+0.4422% +1.6677% +3.3659%] (p = 0.02 < 0.05) + Change within noise threshold. +Found 1 outliers among 10 measurements (10.00%) + 1 (10.00%) high mild + +custimzied MSM with degree 8192, cpu=16 + time: [24.551 ms 26.576 ms 30.854 ms] + change: [+14.974% +27.059% +38.138%] (p = 0.00 < 0.05) + Performance has regressed. + +custimzied MSM with degree 8192, cpu=32 + time: [30.187 ms 32.344 ms 33.676 ms] + change: [+7.7978% +21.365% +33.128%] (p = 0.00 < 0.05) + Performance has regressed. + +halo2 MSM with degree 8192 + time: [5.4164 ms 5.5585 ms 5.6674 ms] + change: [-1.8822% +1.3195% +4.3651%] (p = 0.46 > 0.05) + No change in performance detected. + +arkworks MSM with degree 16384 + time: [11.135 ms 11.229 ms 11.374 ms] + change: [+0.3314% +1.1181% +2.0262%] (p = 0.02 < 0.05) + Change within noise threshold. +Found 1 outliers among 10 measurements (10.00%) + 1 (10.00%) high severe + +custimzied MSM with degree 16384, cpu=4 + time: [54.622 ms 54.782 ms 54.994 ms] + change: [-0.5004% +0.0082% +0.5118%] (p = 0.98 > 0.05) + No change in performance detected. + +custimzied MSM with degree 16384, cpu=8 + time: [36.885 ms 37.015 ms 37.112 ms] + change: [-0.6465% +0.0691% +0.7008%] (p = 0.85 > 0.05) + No change in performance detected. + +custimzied MSM with degree 16384, cpu=16 + time: [28.828 ms 29.302 ms 30.060 ms] + change: [-4.1606% -0.3888% +3.8239%] (p = 0.86 > 0.05) + No change in performance detected. +Found 1 outliers among 10 measurements (10.00%) + 1 (10.00%) high mild + +custimzied MSM with degree 16384, cpu=32 + time: [46.855 ms 51.795 ms 57.535 ms] + change: [+41.566% +52.171% +63.184%] (p = 0.00 < 0.05) + Performance has regressed. + +halo2 MSM with degree 16384 + time: [9.8853 ms 10.604 ms 11.531 ms] + change: [+15.404% +21.090% +25.905%] (p = 0.00 < 0.05) + Performance has regressed. +Found 1 outliers among 10 measurements (10.00%) + 1 (10.00%) low mild + From fd6292e67d90c53ec80263f9eee6a251bc69fea0 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Thu, 13 Jun 2024 18:01:35 -0400 Subject: [PATCH 13/31] fix bug in lagarange bases --- bi-kzg/1.log | 30 ++++++++++++++++++ bi-kzg/script/lagrange.sage | 61 +++++++++++++++++++++++++++++++++++++ bi-kzg/src/bi_kzg.rs | 31 +++++++++++++------ bi-kzg/src/poly.rs | 22 +++++++++++++ bi-kzg/src/tests.rs | 9 ++++-- 5 files changed, 141 insertions(+), 12 deletions(-) create mode 100644 bi-kzg/1.log create mode 100644 bi-kzg/script/lagrange.sage diff --git a/bi-kzg/1.log b/bi-kzg/1.log new file mode 100644 index 00000000..92e101d4 --- /dev/null +++ b/bi-kzg/1.log @@ -0,0 +1,30 @@ + +running 1 test +test tests::test_bi_kzg_e2e ... FAILED + +failures: + +---- tests::test_bi_kzg_e2e stdout ---- +omega 0: 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000 +omega 1: 0x30644e72e131a029048b6e193fd841045cea24f6fd736bec231204708f703636 +n: 2 +m: 4 +start to compute the scalars +lagrange_tau_0: [0x0000000000000000000000000000000000000000000000000000000000000003, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff] +lagrange_tau_1: [0x0000000000000000000000000000000000000000000000000000000000000064, 0x30644e72e1319feebbb9861cf605af3a73ffd18bb2bfea627fa6d5f840d1c959, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffb6, 0x000000000000003afc96bf998b7ba922b43416bcc6f9862ec43b1f9baf2e3690] +lagrange scalars: [0x000000000000000000000000000000000000000000000000000000000000012c, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff39, 0x30644e72e1319f78c28c06e9df0e5cf50b97a41224ccde04f73096c0e2755c09, 0x0000000000000075f92d7f3316f7524568682d798df30c5d88763f375e5c6d50, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff20, 0x0000000000000000000000000000000000000000000000000000000000000096, 0x00000000000000b0f5c43ecca272fb681c9c443654ec928c4cb15ed30d8aa3b0, 0x30644e72e1319fb3bf22c6836a8a0617bfcbbaceebc66433bb6bb65c91a392e1] +start to compute the affine bases +start to compute the lagrange bases +lagrange scalars: [0x000000000000000000000000000000000000000000000000000000000000012c, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff39, 0x30644e72e1319f78c28c06e9df0e5cf50b97a41224ccde04f73096c0e2755c09, 0x0000000000000075f92d7f3316f7524568682d798df30c5d88763f375e5c6d50, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff20, 0x0000000000000000000000000000000000000000000000000000000000000096, 0x00000000000000b0f5c43ecca272fb681c9c443654ec928c4cb15ed30d8aa3b0, 0x30644e72e1319fb3bf22c6836a8a0617bfcbbaceebc66433bb6bb65c91a392e1] +thread 'tests::test_bi_kzg_e2e' panicked at bi-kzg/src/tests.rs:55:5: +assertion `left == right` failed + left: 0x0000000000000000000000000000000000000000000000000000000000014d3d + right: 0x0000000000000000000000000000000000000000000000000000000000002d29 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + + +failures: + tests::test_bi_kzg_e2e + +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 3 filtered out; finished in 0.00s + diff --git a/bi-kzg/script/lagrange.sage b/bi-kzg/script/lagrange.sage new file mode 100644 index 00000000..89da6047 --- /dev/null +++ b/bi-kzg/script/lagrange.sage @@ -0,0 +1,61 @@ +r = 21888242871839275222246405745257275088548364400416034343698204186575808495617 +omega0 = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000 +omega1 = 0x30644e72e131a029048b6e193fd841045cea24f6fd736bec231204708f703636 +n = 2 +m = 4 + +print(omega0^2%r) +print(omega1^4%r) + +P. = PolynomialRing(Zmod(r)) +f = P(1 + 2*x + 3*y + 4*x*y + 5*y^2 + 6*x*y^2 + 7*y^3 + 8*x*y^3) + +omega0_powers = [1, omega0 ] +omega1_powers = [1, omega1, omega1^2 % r, omega1^3 % r] + +f_lag = [] +for o1 in omega1_powers: + for o0 in omega0_powers: + print(o0, o1) + f_lag.append(f(o0, o1)) + +poly_lag_coeff = [0x0000000000000000000000000000000000000000000000000000000000000024, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffffd, 0x00000000000000059e26bcea0d48bac65a4e1a8be2302529067f891b047e4e50, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff9, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x30644e72e131a0241a2988cc74389d96cde5cdbc97894b683d626c78eb81b1a1, 0x0000000000000000000000000000000000000000000000000000000000000000] + +t0 = [] +for i in range(n): + tmp = P(1) + for k in range(n): + if i!=k: + tmp *= P((omega0_powers[k]-x)/(omega0_powers[k]-omega0_powers[i])) + t0.append(tmp) +print("omega0") +for t in t0: + print(t(5, 7)) + +t1 = [] +for i in range(m): + tmp = P(1) + for k in range(m): + if i!=k: + tmp *= P((omega1_powers[k]-y)/(omega1_powers[k]-omega1_powers[i])) + t1.append(tmp) + +print("omega1") +for t in t1: + print(t(5, 7)) + +bases = [] + +for t10 in t1: + for t00 in t0: + t = t00*t10 + bases.append(t) + +res = P(0) +for i in range(n*m): + res += bases[i] * poly_lag_coeff[i] + +print(res - f) +print() +for t in bases: + print(t(5, 7)) \ No newline at end of file diff --git a/bi-kzg/src/bi_kzg.rs b/bi-kzg/src/bi_kzg.rs index 7c881a85..31124be2 100644 --- a/bi-kzg/src/bi_kzg.rs +++ b/bi-kzg/src/bi_kzg.rs @@ -16,7 +16,7 @@ use rand::Rng; use rand::RngCore; use crate::msm::best_multiexp; -use crate::poly::lagrange_coefficients; +use crate::poly::{lagrange_coefficients, lagrange_coefficients_a}; use crate::structs::BivariatePolynomial; use crate::util::parallelize; use crate::{ @@ -51,10 +51,10 @@ where assert!(supported_n.is_power_of_two()); assert!(supported_m.is_power_of_two()); - let tau_0 = E::Fr::random(&mut rng); - let tau_1 = E::Fr::random(&mut rng); - // let tau_0 = E::Fr::from(5); - // let tau_1 = E::Fr::from(7); + // let tau_0 = E::Fr::random(&mut rng); + // let tau_1 = E::Fr::random(&mut rng); + let tau_0 = E::Fr::from(5); + let tau_1 = E::Fr::from(7); let g1 = E::G1Affine::generator(); @@ -67,6 +67,9 @@ where println!("omega 0: {:?}", omega_0); println!("omega 1: {:?}", omega_1); + println!("n: {}", supported_n); + println!("m: {}", supported_m); + assert!( omega_0.pow_vartime(&[supported_n as u64]) == E::Fr::ONE, "omega_0 is not root of unity for supported_n" @@ -83,15 +86,21 @@ where let (scalars, lagrange_scalars) = { let powers_of_omega_0 = powers_of_field_elements(&omega_0, supported_n); let powers_of_tau_0 = powers_of_field_elements(&tau_0, supported_n); - let lagrange_tau_0 = lagrange_coefficients(&powers_of_omega_0, &powers_of_tau_0); + let lagrange_tau_0 = lagrange_coefficients_a(&powers_of_omega_0, &tau_0); let powers_of_omega_1 = powers_of_field_elements(&omega_1, supported_m); let powers_of_tau_1 = powers_of_field_elements(&tau_1, supported_m); - let lagrange_tau_1 = lagrange_coefficients(&powers_of_omega_1, &powers_of_tau_1); + let lagrange_tau_1 = lagrange_coefficients_a(&powers_of_omega_1, &tau_1); let scalars = tensor_product_parallel(&powers_of_tau_0, &powers_of_tau_1); - let largrange_scalars = tensor_product_parallel(&lagrange_tau_0, &lagrange_tau_1); - (scalars, largrange_scalars) + let lagrange_scalars = tensor_product_parallel(&lagrange_tau_0, &lagrange_tau_1); + + + println!("lagrange_tau_0: {:?}", lagrange_tau_0); + println!("lagrange_tau_1: {:?}", lagrange_tau_1); + (scalars, lagrange_scalars) }; + println!("lagrange scalars: {:?} ", lagrange_scalars); + println!("start to compute the affine bases"); let coeff_bases = { let mut proj_bases = vec![E::G1::identity(); supported_n * supported_m]; @@ -179,7 +188,7 @@ where com, com_lag, "commitment is not equal to lagrange commitment" ); - + println!("finished commit"); Self::Commitment { com } } @@ -201,9 +210,11 @@ where let f_tau0_b = polynomial.evaluate(&tau_0, &b); let f_a_tau1 = polynomial.evaluate(&a, &tau_1); + println!("here {:?} {:?} {:?} {:?}", tau_0, tau_1, a, b); let q_0 = (f_tau0_b - u) * ((tau_0 - a).invert().unwrap()); let q_1 = (c - u_prime) * ((tau_1 - b).invert().unwrap()); + println!("here2"); let proof = BiKZGProof { pi0: (prover_param.borrow().powers_of_g[0] * q_0).into(), pi1: (prover_param.borrow().powers_of_g[0] * q_1).into(), diff --git a/bi-kzg/src/poly.rs b/bi-kzg/src/poly.rs index b00845f1..7a58b91c 100644 --- a/bi-kzg/src/poly.rs +++ b/bi-kzg/src/poly.rs @@ -83,6 +83,28 @@ impl BivariatePolynomial { // } } + +/// For x in points, compute the Lagrange coefficients at x given the roots. +/// `L_{i}(x) = \prod_{j \neq i} \frac{x - r_j}{r_i - r_j}`` +pub(crate) fn lagrange_coefficients_a(roots: &[F], points: &F) -> Vec { + roots + .par_iter() + .enumerate() + .map(|(i, _)| { + let mut numerator = F::ONE; + let mut denominator = F::ONE; + for j in 0..roots.len() { + if i == j { + continue; + } + numerator *= roots[j] - points; + denominator *= roots[j] - roots[i]; + } + numerator * denominator.invert().unwrap() + }) + .collect() +} + /// For x in points, compute the Lagrange coefficients at x given the roots. /// `L_{i}(x) = \prod_{j \neq i} \frac{x - r_j}{r_i - r_j}`` pub(crate) fn lagrange_coefficients(roots: &[F], points: &[F]) -> Vec { diff --git a/bi-kzg/src/tests.rs b/bi-kzg/src/tests.rs index cbbf2ea1..ed3122f1 100644 --- a/bi-kzg/src/tests.rs +++ b/bi-kzg/src/tests.rs @@ -49,8 +49,13 @@ fn test_bi_kzg_e2e() { ); // let poly = BivariatePolynomial::random(&mut rng, n, m); - let x = Fr::from(5u64); - let y = Fr::from(6u64); + let x = Fr::from(9u64); + let y = Fr::from(10u64); + + assert_eq!(poly.evaluate(&x, &y), Fr::from(85309u64)); + + println!("poly lag coeff: {:?}", poly.lagrange_coeffs()); + let commit = BiKZG::::commit(&srs, &poly); let (proof, eval) = BiKZG::::open(&srs, &poly, &(x, y)); From d54a9e7346a8936f75254505505f8ea9c6a8ffa0 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Thu, 13 Jun 2024 20:22:52 -0400 Subject: [PATCH 14/31] wip --- .github/workflows/ci.yml | 2 +- Cargo.toml | 5 ++ bi-kzg/Cargo.toml | 1 + bi-kzg/script/lagrange.sage | 2 + bi-kzg/src/bi_kzg.rs | 141 ++++++++++++++++++++++++++------ bi-kzg/src/poly.rs | 157 +++++++++++++++++++++++++++++++----- bi-kzg/src/structs.rs | 6 +- bi-kzg/src/tests.rs | 31 ++----- 8 files changed, 272 insertions(+), 73 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bed27f81..5c925200 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,4 +75,4 @@ jobs: - run: RUSTFLAGS="-C target-feature=+avx2" cargo test --no-default-features --release - run: RUSTFLAGS="-C target-feature=+avx2" cargo test --all-features --release - run: RUSTFLAGS="-C target-feature=+avx2" cargo run --release -- -t 4 -f 31 - - run: RUSTFLAGS="-C target-feature=+avx2" cargo run --release -- -t 4 -f 254 + - run: RUSTFLAGS="-C target-feature=+avx2" cargo run --release -- -t 4 -f 254 diff --git a/Cargo.toml b/Cargo.toml index 3f9668d3..1fe0ccbd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,12 @@ members = [ [workspace.dependencies] ark-std = "0.4" +ark-bn254 = "0.4.0" +ark-ec = "0.4.0" +ark-ff = { version = "0.4", features = [ "asm" ] } clap = { version = "4.1", features = ["derive"] } +criterion = { version = "0.5", features = ["html_reports"] } +itertools = "0.13" log = "0.4" rand = "0.8.5" rayon = "1.10" diff --git a/bi-kzg/Cargo.toml b/bi-kzg/Cargo.toml index c1ab6398..78005917 100644 --- a/bi-kzg/Cargo.toml +++ b/bi-kzg/Cargo.toml @@ -8,6 +8,7 @@ ark-std.workspace = true clap.workspace = true halo2curves.workspace = true log.workspace = true +itertools.workspace = true rand.workspace = true rayon.workspace = true sha2.workspace = true diff --git a/bi-kzg/script/lagrange.sage b/bi-kzg/script/lagrange.sage index 89da6047..57e4c943 100644 --- a/bi-kzg/script/lagrange.sage +++ b/bi-kzg/script/lagrange.sage @@ -1,3 +1,5 @@ +# this script is used to generate test vectors for bi-kzg + r = 21888242871839275222246405745257275088548364400416034343698204186575808495617 omega0 = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000 omega1 = 0x30644e72e131a029048b6e193fd841045cea24f6fd736bec231204708f703636 diff --git a/bi-kzg/src/bi_kzg.rs b/bi-kzg/src/bi_kzg.rs index 31124be2..471785ce 100644 --- a/bi-kzg/src/bi_kzg.rs +++ b/bi-kzg/src/bi_kzg.rs @@ -1,9 +1,11 @@ use std::ops::{Add, AddAssign}; use std::process::Output; +use std::thread; use std::{borrow::Borrow, marker::PhantomData, slice::ChunkBy}; use halo2curves::ff::Field; use halo2curves::ff::PrimeField; +use halo2curves::fft::best_fft; use halo2curves::group::prime::PrimeCurveAffine; use halo2curves::group::Curve; use halo2curves::group::Group; @@ -16,7 +18,7 @@ use rand::Rng; use rand::RngCore; use crate::msm::best_multiexp; -use crate::poly::{lagrange_coefficients, lagrange_coefficients_a}; +use crate::poly::{lagrange_coefficients, univariate_quotient}; use crate::structs::BivariatePolynomial; use crate::util::parallelize; use crate::{ @@ -83,20 +85,26 @@ where println!("start to compute the scalars"); // computes the vector of L_i^N(tau_0) * L_j^M(tau_1) for i in 0..supported_n and j in 0..supported_m - let (scalars, lagrange_scalars) = { + let (scalars, powers_of_tau_0, lagrange_scalars) = { let powers_of_omega_0 = powers_of_field_elements(&omega_0, supported_n); let powers_of_tau_0 = powers_of_field_elements(&tau_0, supported_n); - let lagrange_tau_0 = lagrange_coefficients_a(&powers_of_omega_0, &tau_0); + let lagrange_tau_0 = lagrange_coefficients(&powers_of_omega_0, &tau_0); let powers_of_omega_1 = powers_of_field_elements(&omega_1, supported_m); let powers_of_tau_1 = powers_of_field_elements(&tau_1, supported_m); - let lagrange_tau_1 = lagrange_coefficients_a(&powers_of_omega_1, &tau_1); + let lagrange_tau_1 = lagrange_coefficients(&powers_of_omega_1, &tau_1); let scalars = tensor_product_parallel(&powers_of_tau_0, &powers_of_tau_1); let lagrange_scalars = tensor_product_parallel(&lagrange_tau_0, &lagrange_tau_1); + // let mut f_x_b_scalars = lagrange_tau_0.clone(); + // powers_of_tau_1.iter().skip(1).for_each(|bi| { + // f_x_b_scalars + // .iter_mut() + // .zip(lagrange_tau_0.iter()) + // .for_each(|(fi, li)| *fi += *bi * *li); + // }); - println!("lagrange_tau_0: {:?}", lagrange_tau_0); - println!("lagrange_tau_1: {:?}", lagrange_tau_1); - (scalars, lagrange_scalars) + // (scalars, f_x_b_scalars, lagrange_scalars) + (scalars, powers_of_tau_0, lagrange_scalars) }; println!("lagrange scalars: {:?} ", lagrange_scalars); @@ -120,6 +128,27 @@ where }; println!("start to compute the lagrange bases"); + + let powers_of_tau_0 = { + let mut proj_bases = vec![E::G1::identity(); supported_n]; + parallelize(&mut proj_bases, |g, start| { + for (idx, g) in g.iter_mut().enumerate() { + let offset = start + idx; + *g = g1 * powers_of_tau_0[offset]; + } + }); + + let mut affine_bases = vec![E::G1Affine::identity(); supported_n]; + parallelize(&mut affine_bases, |affine_bases, starts| { + E::G1::batch_normalize( + &proj_bases[starts..(starts + affine_bases.len())], + affine_bases, + ); + }); + drop(proj_bases); + affine_bases + }; + println!("lagrange scalars: {:?} ", lagrange_scalars); let lagrange_bases = { let mut proj_bases = vec![E::G1::identity(); supported_n * supported_m]; @@ -130,22 +159,23 @@ where } }); - let mut g_lagrange = vec![E::G1Affine::identity(); supported_n * supported_m]; - parallelize(&mut g_lagrange, |g_lagrange, starts| { + let mut affine_bases = vec![E::G1Affine::identity(); supported_n * supported_m]; + parallelize(&mut affine_bases, |affine_bases, starts| { E::G1::batch_normalize( - &proj_bases[starts..(starts + g_lagrange.len())], - g_lagrange, + &proj_bases[starts..(starts + affine_bases.len())], + affine_bases, ); }); drop(proj_bases); - g_lagrange + affine_bases }; BiKZGSRS { tau_0, tau_1, powers_of_g: coeff_bases, - powers_of_g_lagrange: lagrange_bases, + powers_of_tau_0: powers_of_tau_0, + powers_of_g_lagrange_over_both_roots: lagrange_bases, h: E::G2Affine::generator(), tau_0_h: (E::G2Affine::generator() * tau_0).into(), tau_1_h: (E::G2Affine::generator() * tau_1).into(), @@ -177,17 +207,32 @@ where .into(), "commitment is not equal to evaluation" ); + { + let lag_coeff = poly.lagrange_coeffs(); + let com_lag = best_multiexp( + &lag_coeff, + prover_param + .borrow() + .powers_of_g_lagrange_over_both_roots + .as_slice(), + ) + .into(); + assert_eq!( + com, com_lag, + "commitment is not equal to lagrange commitment" + ); + } + + { + let lag_coeff = poly.evaluate_y(&prover_param.borrow().tau_1); + let com_lag = + best_multiexp(&lag_coeff, prover_param.borrow().powers_of_tau_0.as_slice()).into(); + assert_eq!( + com, com_lag, + "commitment is not equal to lagrange commitment" + ); + } - let lag_coeff = poly.lagrange_coeffs(); - let com_lag = best_multiexp( - &lag_coeff, - prover_param.borrow().powers_of_g_lagrange.as_slice(), - ) - .into(); - assert_eq!( - com, com_lag, - "commitment is not equal to lagrange commitment" - ); println!("finished commit"); Self::Commitment { com } } @@ -197,6 +242,55 @@ where polynomial: &Self::Polynomial, point: &Self::Point, ) -> (Self::Proof, Self::Evaluation) { + let pi_0 = { + let f_x_b = polynomial.evaluate_y(&point.1); + let q_0_x_b = univariate_quotient(&f_x_b, &point.1); + best_multiexp( + &q_0_x_b, + prover_param.borrow().powers_of_tau_0.as_slice(), + ) + .to_affine() + }; + + let pi_1 = { + + // // let domain = Domain::::new_for_size(prover_param.borrow().powers_of_g_lagrange_over_both_roots.len() as u64).unwrap(); + + // let bases = prover_param.borrow().powers_of_g_lagrange_over_both_roots.as_slice(); + // let mut q_1_x_y = vec![]; + // let lag_bases = (0..polynomial.degree_0*polynomial.degree_1).map(|i|E::Fr::from(i as u64)). collect::>(); + // let mut cb = vec![E::Fr::from(0);polynomial.degree_0*polynomial.degree_1]; + // for i in 0..1 { + // let start = 0; + // let mut end = polynomial.degree_0; + // if end > polynomial.degree_0 {end = polynomial.degree_0;} + // let handle = thread::spawn(move || { + // // let cb_ptr = cb_ptr_usize as *mut E::Fr; + // // let mut lag_base_ptr = lag_base_ptr_usize as *const Fr; + // // lag_base_ptr = unsafe { lag_base_ptr.offset((start * degree_m) as isize)}; + // for j in start..end { + // let mut cj = vec![E::Fr::from(0);polynomial.degree_0]; + // // lag_base_ptr = unsafe { lag_base_ptr.offset(degree_m as isize)}; + // // domain1.ifft_in_place(&mut cj); + // best_fft(&mut cj, ); + + + // let mut cb_temp = cj[degree_m-1]; + // unsafe{ cb_ptr.add(j*degree_m + degree_m - 1).write(cb_temp) }; + // for k in (1..(degree_m-1)).rev() { + // cb_temp *= b; + // cb_temp += cj[k]; + // unsafe{ cb_ptr.add(j*degree_m + k).write(cb_temp) }; + // } + // } + // }); + // handles.push(handle); + // } + + + }; + + // fixme let tau_0 = prover_param.borrow().tau_0; let tau_1 = prover_param.borrow().tau_1; @@ -225,6 +319,7 @@ where let right = c - u; assert_eq!(t0 + t1, right, "t0 + t1 != right"); + assert_eq!(pi_0, proof.pi0, "pi0 != pi_0"); (proof, u) } diff --git a/bi-kzg/src/poly.rs b/bi-kzg/src/poly.rs index 7a58b91c..2deed6bb 100644 --- a/bi-kzg/src/poly.rs +++ b/bi-kzg/src/poly.rs @@ -1,6 +1,8 @@ use halo2curves::ff::{Field, PrimeField}; +use itertools::Itertools; use rand::RngCore; use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; +use rayon::vec; use crate::structs::{BivariateLagrangePolynomial, BivariatePolynomial}; use crate::util::powers_of_field_elements; @@ -39,6 +41,23 @@ impl BivariatePolynomial { }) } + pub fn evaluate_y(&self, y: &F) -> Vec { + let mut f_x_b = self.coefficients[0..self.degree_0].to_vec(); + let powers_of_b = powers_of_field_elements(y, self.degree_1); + powers_of_b + .iter() + .zip_eq(self.coefficients.chunks_exact(self.degree_0)) + .skip(1) + .for_each(|(bi, chunk_i)| { + f_x_b + .iter_mut() + .zip(chunk_i.iter()) + .for_each(|(f, c)| *f += *c * *bi) + }); + + f_x_b + } + /// pub fn lagrange_coeffs(&self) -> Vec { // roots of unity for supported_n and supported_m @@ -83,10 +102,9 @@ impl BivariatePolynomial { // } } - /// For x in points, compute the Lagrange coefficients at x given the roots. /// `L_{i}(x) = \prod_{j \neq i} \frac{x - r_j}{r_i - r_j}`` -pub(crate) fn lagrange_coefficients_a(roots: &[F], points: &F) -> Vec { +pub(crate) fn lagrange_coefficients(roots: &[F], points: &F) -> Vec { roots .par_iter() .enumerate() @@ -105,27 +123,60 @@ pub(crate) fn lagrange_coefficients_a(roots: &[F], point .collect() } -/// For x in points, compute the Lagrange coefficients at x given the roots. -/// `L_{i}(x) = \prod_{j \neq i} \frac{x - r_j}{r_i - r_j}`` -pub(crate) fn lagrange_coefficients(roots: &[F], points: &[F]) -> Vec { - roots - .par_iter() - .enumerate() - .map(|(i, _)| { - let mut numerator = F::ONE; - let mut denominator = F::ONE; - for j in 0..roots.len() { - if i == j { - continue; - } - numerator *= roots[j] - points[i]; - denominator *= roots[j] - roots[i]; - } - numerator * denominator.invert().unwrap() - }) - .collect() +/// Compute poly / (x-point) +/// +// TODO: this algorithm is quadratic. is this more efficient than FFT? +pub(crate) fn univariate_quotient(poly: &[F], point: &F) -> Vec { + let mut dividend_coeff = poly.to_vec(); + let divisor = vec![-*point, F::from(1u64)]; + let mut coefficients = vec![]; + + let mut dividend_pos = dividend_coeff.len() - 1; + let divisor_pos = divisor.len() - 1; + let mut difference = dividend_pos as isize - divisor_pos as isize; + + while difference >= 0 { + let term_quotient = dividend_coeff[dividend_pos] * divisor[divisor_pos].invert().unwrap(); + coefficients.push(term_quotient); + + for i in (0..=divisor_pos).rev() { + let difference = difference as usize; + let x = divisor[i]; + let y = x * term_quotient; + let z = dividend_coeff[difference + i]; + dividend_coeff[difference + i] = z - y; + } + + dividend_pos -= 1; + difference -= 1; + } + coefficients.reverse(); + coefficients.push(F::from(0u64)); + + coefficients } +// /// For x in points, compute the Lagrange coefficients at x given the roots. +// /// `L_{i}(x) = \prod_{j \neq i} \frac{x - r_j}{r_i - r_j}`` +// pub(crate) fn lagrange_coefficients(roots: &[F], points: &[F]) -> Vec { +// roots +// .par_iter() +// .enumerate() +// .map(|(i, _)| { +// let mut numerator = F::ONE; +// let mut denominator = F::ONE; +// for j in 0..roots.len() { +// if i == j { +// continue; +// } +// numerator *= roots[j] - points[i]; +// denominator *= roots[j] - roots[i]; +// } +// numerator * denominator.invert().unwrap() +// }) +// .collect() +// } + impl BivariateLagrangePolynomial { fn new(coeffs: Vec, degree_0: usize, degree_1: usize) -> Self { assert_eq!(coeffs.len(), degree_0 * degree_1); @@ -236,6 +287,70 @@ mod tests { ); } + #[test] + fn test_eval_at_y() { + let poly = BivariatePolynomial::new( + vec![ + Fr::from(1u64), + Fr::from(2u64), + Fr::from(3u64), + Fr::from(4u64), + Fr::from(5u64), + Fr::from(6u64), + Fr::from(7u64), + Fr::from(8u64), + ], + 2, + 4, + ); + let eval_at_y = poly.evaluate_y(&Fr::from(10u64)); + assert_eq!(eval_at_y, vec![Fr::from(7531u64), Fr::from(8642u64)]); + } + + #[test] + fn test_poly_div() { + { + // x^3 + 1 = (x + 1)(x^2 - x + 1) + let poly = vec![ + Fr::from(1u64), + Fr::from(0u64), + Fr::from(0u64), + Fr::from(1u64), + ]; + let point = -Fr::from(1u64); + let result = super::univariate_quotient(&poly, &point); + assert_eq!( + result, + vec![ + Fr::from(1u64), + -Fr::from(1u64), + Fr::from(1u64), + Fr::from(0u64) + ] + ); + } + { + // x^3 - 1 = (x-1)(x^2 + x + 1) + let poly = vec![ + -Fr::from(1u64), + Fr::from(0u64), + Fr::from(0u64), + Fr::from(1u64), + ]; + let point = Fr::from(1u64); + let result = super::univariate_quotient(&poly, &point); + assert_eq!( + result, + vec![ + Fr::from(1u64), + Fr::from(1u64), + Fr::from(1u64), + Fr::from(0u64) + ] + ); + } + } + // #[test] // fn test_lagrange_coeffs() { // let poly = BivariatePolynomial::new( diff --git a/bi-kzg/src/structs.rs b/bi-kzg/src/structs.rs index 8d25f512..c6792366 100644 --- a/bi-kzg/src/structs.rs +++ b/bi-kzg/src/structs.rs @@ -30,8 +30,10 @@ pub struct BiKZGSRS { /// ..., g_1^{\tau_0^N\tau_1^M} /// ) pub powers_of_g: Vec, - /// g in lagrange form - pub powers_of_g_lagrange: Vec, + /// g in lagrange form over omega_0 + pub powers_of_tau_0: Vec, + /// g in lagrange form over omega_0 and omega_1 + pub powers_of_g_lagrange_over_both_roots: Vec, /// The generator of G2. pub h: E::G2Affine, /// tau_0 times the above generator of G2. diff --git a/bi-kzg/src/tests.rs b/bi-kzg/src/tests.rs index ed3122f1..f6193c03 100644 --- a/bi-kzg/src/tests.rs +++ b/bi-kzg/src/tests.rs @@ -6,26 +6,6 @@ use crate::{ util::tensor_product_parallel, BivariatePolynomial, }; -// #[test] -// fn test_interpolation() { -// let f = (0..8).map(|x| Fr::from(x as u64)).collect::>(); -// let f = BivariatePolynomial::new(f, 2, 4); -// let r1 = (0..2).map(|x| Fr::from(x as u64)).collect::>(); -// let r2 = (0..4).map(|x| Fr::from(x as u64)).collect::>(); - -// let evals = r2 -// .iter() -// .flat_map(|r2| { -// r1.iter() -// .map(|&r1| f.evaluate(&r1, &r2)) -// .collect::>() -// }) -// .collect::>(); - -// let power - -// } - #[test] fn test_bi_kzg_e2e() { let mut rng = test_rng(); @@ -56,7 +36,6 @@ fn test_bi_kzg_e2e() { println!("poly lag coeff: {:?}", poly.lagrange_coeffs()); - let commit = BiKZG::::commit(&srs, &poly); let (proof, eval) = BiKZG::::open(&srs, &poly, &(x, y)); @@ -72,13 +51,13 @@ fn test_bi_kzg_e2e() { } #[test] -fn test_lagrange_eval() { +fn test_lagrange_coeffs() { let roots = vec![Fr::from(1u64), Fr::from(2u64), Fr::from(3u64)]; - let points = vec![Fr::from(4u64), Fr::from(5u64), Fr::from(6u64)]; - let result = lagrange_coefficients(&roots, &points); + let point = Fr::from(4u64); + let result = lagrange_coefficients(&roots, &point); assert_eq!(result[0], Fr::from(1u64)); - assert_eq!(result[1], -Fr::from(8u64)); - assert_eq!(result[2], Fr::from(10u64)); + assert_eq!(result[1], -Fr::from(3u64)); + assert_eq!(result[2], Fr::from(3u64)); } #[test] From 81668eee37159bb8a3cbec6894b9b9d9e3079c78 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Thu, 13 Jun 2024 20:26:49 -0400 Subject: [PATCH 15/31] 1 --- bi-kzg/src/bi_kzg.rs | 21 +++++++++++---------- bi-kzg/src/structs.rs | 4 ++-- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/bi-kzg/src/bi_kzg.rs b/bi-kzg/src/bi_kzg.rs index 471785ce..6fb8b42c 100644 --- a/bi-kzg/src/bi_kzg.rs +++ b/bi-kzg/src/bi_kzg.rs @@ -170,11 +170,13 @@ where affine_bases }; + assert_eq!(coeff_bases[..supported_n], powers_of_tau_0); + BiKZGSRS { tau_0, tau_1, powers_of_g: coeff_bases, - powers_of_tau_0: powers_of_tau_0, + // powers_of_tau_0: powers_of_tau_0, powers_of_g_lagrange_over_both_roots: lagrange_bases, h: E::G2Affine::generator(), tau_0_h: (E::G2Affine::generator() * tau_0).into(), @@ -225,8 +227,11 @@ where { let lag_coeff = poly.evaluate_y(&prover_param.borrow().tau_1); - let com_lag = - best_multiexp(&lag_coeff, prover_param.borrow().powers_of_tau_0.as_slice()).into(); + let com_lag = best_multiexp( + &lag_coeff, + prover_param.borrow().powers_of_g[..poly.degree_0].as_ref(), + ) + .into(); assert_eq!( com, com_lag, "commitment is not equal to lagrange commitment" @@ -243,11 +248,11 @@ where point: &Self::Point, ) -> (Self::Proof, Self::Evaluation) { let pi_0 = { - let f_x_b = polynomial.evaluate_y(&point.1); - let q_0_x_b = univariate_quotient(&f_x_b, &point.1); + let f_x_b = polynomial.evaluate_y(&point.1); + let q_0_x_b = univariate_quotient(&f_x_b, &point.1); best_multiexp( &q_0_x_b, - prover_param.borrow().powers_of_tau_0.as_slice(), + prover_param.borrow().powers_of_g[..polynomial.degree_0].as_ref(), ) .to_affine() }; @@ -273,7 +278,6 @@ where // // lag_base_ptr = unsafe { lag_base_ptr.offset(degree_m as isize)}; // // domain1.ifft_in_place(&mut cj); // best_fft(&mut cj, ); - // let mut cb_temp = cj[degree_m-1]; // unsafe{ cb_ptr.add(j*degree_m + degree_m - 1).write(cb_temp) }; @@ -286,11 +290,8 @@ where // }); // handles.push(handle); // } - - }; - // fixme let tau_0 = prover_param.borrow().tau_0; let tau_1 = prover_param.borrow().tau_1; diff --git a/bi-kzg/src/structs.rs b/bi-kzg/src/structs.rs index c6792366..745bcec1 100644 --- a/bi-kzg/src/structs.rs +++ b/bi-kzg/src/structs.rs @@ -30,8 +30,8 @@ pub struct BiKZGSRS { /// ..., g_1^{\tau_0^N\tau_1^M} /// ) pub powers_of_g: Vec, - /// g in lagrange form over omega_0 - pub powers_of_tau_0: Vec, + // /// g in lagrange form over omega_0 + // pub powers_of_tau_0: Vec, /// g in lagrange form over omega_0 and omega_1 pub powers_of_g_lagrange_over_both_roots: Vec, /// The generator of G2. From a776647eeec6183ad3e5b5768d8213b0f06d0fe6 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Thu, 13 Jun 2024 22:05:24 -0400 Subject: [PATCH 16/31] prob pass tests --- bi-kzg/script/lagrange.sage | 51 +++++++++++++- bi-kzg/src/bi_kzg.rs | 121 +++++++++++++++++++++++++------- bi-kzg/src/poly.rs | 133 +++++++++++++++++++++++++++--------- bi-kzg/src/structs.rs | 8 +-- bi-kzg/src/tests.rs | 35 +++++++--- 5 files changed, 274 insertions(+), 74 deletions(-) diff --git a/bi-kzg/script/lagrange.sage b/bi-kzg/script/lagrange.sage index 57e4c943..999ed298 100644 --- a/bi-kzg/script/lagrange.sage +++ b/bi-kzg/script/lagrange.sage @@ -60,4 +60,53 @@ for i in range(n*m): print(res - f) print() for t in bases: - print(t(5, 7)) \ No newline at end of file + print(t(5, 7)) + + + +#P. = PolynomialRing(ZZ) +f = P((x+1)*(y^3+1)) + +f_lag = [] +for o1 in omega1_powers: + for o0 in omega0_powers: + print(o0, o1) + f_lag.append(f(o0, o1)) +print(f) +print(f_lag) + +g = f/P(y+1) +g_lag = [] +for o1 in omega1_powers: + for o0 in omega0_powers: + print(o0, o1) + g_lag.append(g(o0, o1)) +print(g) +print(g_lag) + +t = P(y+1) +t_lag = [] +for o1 in omega1_powers: + for o0 in omega0_powers: + print(o0, o1) + t_lag.append(t(o0, o1)) +print(t) +print(t_lag) + +for i in range(8): + print(f_lag[i] - g_lag[i] *t_lag[i]) + +g_rec = P(0) +for i in range(8): + g_rec += bases[i] * g_lag[i] +print(g_rec) + +f_rec = P(0) +for i in range(8): + f_rec += bases[i] * f_lag[i] +print(f_rec) + +t_rec = P(0) +for i in range(8): + t_rec += bases[i] * t_lag[i] +print(t_rec) \ No newline at end of file diff --git a/bi-kzg/src/bi_kzg.rs b/bi-kzg/src/bi_kzg.rs index 6fb8b42c..c2662e05 100644 --- a/bi-kzg/src/bi_kzg.rs +++ b/bi-kzg/src/bi_kzg.rs @@ -14,6 +14,7 @@ use halo2curves::group::Group; use halo2curves::pairing::{MillerLoopResult, MultiMillerLoop}; use halo2curves::pasta::pallas::Scalar; use halo2curves::CurveAffine; +use itertools::Itertools; use rand::Rng; use rand::RngCore; @@ -85,7 +86,7 @@ where println!("start to compute the scalars"); // computes the vector of L_i^N(tau_0) * L_j^M(tau_1) for i in 0..supported_n and j in 0..supported_m - let (scalars, powers_of_tau_0, lagrange_scalars) = { + let (scalars, f_x_b_scalars, lagrange_scalars) = { let powers_of_omega_0 = powers_of_field_elements(&omega_0, supported_n); let powers_of_tau_0 = powers_of_field_elements(&tau_0, supported_n); let lagrange_tau_0 = lagrange_coefficients(&powers_of_omega_0, &tau_0); @@ -95,16 +96,18 @@ where let scalars = tensor_product_parallel(&powers_of_tau_0, &powers_of_tau_1); let lagrange_scalars = tensor_product_parallel(&lagrange_tau_0, &lagrange_tau_1); - // let mut f_x_b_scalars = lagrange_tau_0.clone(); - // powers_of_tau_1.iter().skip(1).for_each(|bi| { - // f_x_b_scalars - // .iter_mut() - // .zip(lagrange_tau_0.iter()) - // .for_each(|(fi, li)| *fi += *bi * *li); - // }); + let mut f_x_b_scalars = lagrange_tau_0.clone(); + powers_of_tau_1.iter().skip(1).for_each(|bi| { + f_x_b_scalars + .iter_mut() + .zip(lagrange_tau_0.iter()) + .for_each(|(fi, li)| *fi += *bi * *li); + }); + + println!("f_x_b_scalars: {:?}", f_x_b_scalars); - // (scalars, f_x_b_scalars, lagrange_scalars) - (scalars, powers_of_tau_0, lagrange_scalars) + (scalars, f_x_b_scalars, lagrange_scalars) + // (scalars, powers_of_tau_0, lagrange_scalars) }; println!("lagrange scalars: {:?} ", lagrange_scalars); @@ -129,12 +132,12 @@ where println!("start to compute the lagrange bases"); - let powers_of_tau_0 = { + let f_x_b_scalars = { let mut proj_bases = vec![E::G1::identity(); supported_n]; parallelize(&mut proj_bases, |g, start| { for (idx, g) in g.iter_mut().enumerate() { let offset = start + idx; - *g = g1 * powers_of_tau_0[offset]; + *g = g1 * f_x_b_scalars[offset]; } }); @@ -170,13 +173,13 @@ where affine_bases }; - assert_eq!(coeff_bases[..supported_n], powers_of_tau_0); + // assert_eq!(coeff_bases[..supported_n], f_x_b_scalars); BiKZGSRS { tau_0, tau_1, powers_of_g: coeff_bases, - // powers_of_tau_0: powers_of_tau_0, + f_x_b_scalars: f_x_b_scalars, powers_of_g_lagrange_over_both_roots: lagrange_bases, h: E::G2Affine::generator(), tau_0_h: (E::G2Affine::generator() * tau_0).into(), @@ -247,18 +250,85 @@ where polynomial: &Self::Polynomial, point: &Self::Point, ) -> (Self::Proof, Self::Evaluation) { - let pi_0 = { + let (pi_0, f_x_b) = { let f_x_b = polynomial.evaluate_y(&point.1); let q_0_x_b = univariate_quotient(&f_x_b, &point.1); - best_multiexp( + let pi_0 = best_multiexp( &q_0_x_b, + // prover_param.borrow().f_x_b_scalars.as_ref(), prover_param.borrow().powers_of_g[..polynomial.degree_0].as_ref(), ) - .to_affine() + .to_affine(); + (pi_0, f_x_b) }; + // fixme + let tau_0 = prover_param.borrow().tau_0; + let tau_1 = prover_param.borrow().tau_1; + let a = point.0; + let b = point.1; + let c = polynomial.evaluate(&tau_0, &tau_1); + let u = polynomial.evaluate(&a, &b); + // let u_prime = polynomial.evaluate(&tau_0, &b); let pi_1 = { + let mut t = polynomial.clone(); + // t.coefficients[0] -= u_prime; + t.coefficients + .iter_mut() + .take(polynomial.degree_0) + .zip_eq(f_x_b.iter()) + .for_each(|(c, f)| *c -= f); + let coeffs = t.lagrange_coeffs(); + + let mut divisor = vec![E::Fr::from(0); polynomial.degree_0 * polynomial.degree_1]; + divisor[0] = -point.1; + divisor[polynomial.degree_0] = E::Fr::ONE; + let divisor = + BivariatePolynomial::new(divisor, polynomial.degree_0, polynomial.degree_1); + + // let omega = E::Fr::ROOT_OF_UNITY; + // let omega_1 = omega.pow_vartime(&[(1 << E::Fr::S) / polynomial.degree_1 as u64]); + // let divisor = fft_slow(divisor.as_ref(), &omega_1); + let divisor = divisor.lagrange_coeffs(); + + // let omega = E::Fr::ROOT_OF_UNITY; + // let omega_1 = omega.pow_vartime(&[(1 << E::Fr::S) / polynomial.degree_1 as u64]); + // let powers_of_omega_1 = powers_of_field_elements(&omega_1, polynomial.degree_1); + + // todo: batch invert + let y_minus_a_inv_lag = divisor + .iter() + .map(|o| { + if o.is_zero_vartime() { + // E::Fr::ZERO + panic!("not invertible") + } else { + o.invert().unwrap() + } + }) + .collect::>(); + // let mut q_1_x_y = vec![]; + // for i in 0..polynomial.degree_0 { + // for j in 0..polynomial.degree_1{ + // q_1_x_y.push((coeffs[j*polynomial.degree_0 + i] - f_x_b[i]) * y_minus_a_inv_lag[j]); + // } + // } + let q_1_x_y = coeffs + .iter() + .zip_eq(y_minus_a_inv_lag.iter()) + .map(|(c, y)| (*c) * *y) + .collect::>(); + + best_multiexp( + &q_1_x_y, + prover_param + .borrow() + // .powers_of_g + .powers_of_g_lagrange_over_both_roots + .as_ref(), + ) + .to_affine() // // let domain = Domain::::new_for_size(prover_param.borrow().powers_of_g_lagrange_over_both_roots.len() as u64).unwrap(); // let bases = prover_param.borrow().powers_of_g_lagrange_over_both_roots.as_slice(); @@ -292,14 +362,7 @@ where // } }; - // fixme - let tau_0 = prover_param.borrow().tau_0; - let tau_1 = prover_param.borrow().tau_1; - let a = point.0; - let b = point.1; - let c = polynomial.evaluate(&tau_0, &tau_1); - - let u = polynomial.evaluate(&a, &b); + // let u = polynomial.evaluate(&a, &b); let u_prime = polynomial.evaluate(&tau_0, &b); let f_tau0_b = polynomial.evaluate(&tau_0, &b); @@ -310,7 +373,7 @@ where let q_1 = (c - u_prime) * ((tau_1 - b).invert().unwrap()); println!("here2"); - let proof = BiKZGProof { + let proof = BiKZGProof:: { pi0: (prover_param.borrow().powers_of_g[0] * q_0).into(), pi1: (prover_param.borrow().powers_of_g[0] * q_1).into(), }; @@ -321,6 +384,12 @@ where assert_eq!(t0 + t1, right, "t0 + t1 != right"); assert_eq!(pi_0, proof.pi0, "pi0 != pi_0"); + assert_eq!(pi_1, proof.pi1, "pi1 != pi_1"); + + let proof2 = BiKZGProof:: { + pi0: pi_0, + pi1: pi_1, + }; (proof, u) } diff --git a/bi-kzg/src/poly.rs b/bi-kzg/src/poly.rs index 2deed6bb..8f4730f0 100644 --- a/bi-kzg/src/poly.rs +++ b/bi-kzg/src/poly.rs @@ -78,11 +78,11 @@ impl BivariatePolynomial { }; let powers_of_omega_0 = powers_of_field_elements(&omega_0, self.degree_0); let powers_of_omega_1 = powers_of_field_elements(&omega_1, self.degree_1); - println!( - "omega len {} {}", - powers_of_omega_0.len(), - powers_of_omega_1.len() - ); + // println!( + // "omega len {} {}", + // powers_of_omega_0.len(), + // powers_of_omega_1.len() + // ); // Todo! Optimize me. This is not efficient. let mut res = vec![]; @@ -91,8 +91,8 @@ impl BivariatePolynomial { res.push(self.evaluate(omega_0_power, omega_1_power)); } } - - println!("res: {:?}", res); + // println!("powers_of_omega_1: {:?}", powers_of_omega_1); + // println!("res: {:?}", res); res } @@ -156,6 +156,20 @@ pub(crate) fn univariate_quotient(poly: &[F], point: &F) -> Vec(coeffs: &[F], omega: &F) -> Vec { +// let n = coeffs.len(); +// let mut res = vec![F::ZERO; n]; +// for i in 0..n { +// let mut omega_i = F::ONE; +// for j in 0..n { +// res[i] += omega_i * coeffs[j]; +// omega_i *= omega; +// } +// } +// res +// } + // /// For x in points, compute the Lagrange coefficients at x given the roots. // /// `L_{i}(x) = \prod_{j \neq i} \frac{x - r_j}{r_i - r_j}`` // pub(crate) fn lagrange_coefficients(roots: &[F], points: &[F]) -> Vec { @@ -305,6 +319,22 @@ mod tests { ); let eval_at_y = poly.evaluate_y(&Fr::from(10u64)); assert_eq!(eval_at_y, vec![Fr::from(7531u64), Fr::from(8642u64)]); + + let poly = BivariatePolynomial::new( + vec![ + Fr::from(1u64), + Fr::from(0u64), + Fr::from(1u64), + Fr::from(0u64), + Fr::from(0u64), + Fr::from(0u64), + Fr::from(0u64), + Fr::from(0u64), + ], + 2, + 4, + ); + println!("poly: {:?}", poly.lagrange_coeffs()); } #[test] @@ -351,29 +381,68 @@ mod tests { } } - // #[test] - // fn test_lagrange_coeffs() { - // let poly = BivariatePolynomial::new( - // vec![ - // Fr::from(1u64), - // Fr::from(2u64), - // Fr::from(3u64), - // Fr::from(4u64), - // Fr::from(5u64), - // Fr::from(10u64), - // Fr::from(15u64), - // Fr::from(20u64), - // ], - // 4, - // 2, - // ); - - // let lagrange_coeffs = poly.lagrange_coeffs(); - // println!("lag: {:?}", lagrange_coeffs); - // assert_eq!(lagrange_coeffs.len(), 8); - // assert_eq!(lagrange_coeffs[0], Fr::from(1u64)); - // assert_eq!(lagrange_coeffs[1], Fr::from(2u64)); - // assert_eq!(lagrange_coeffs[2], Fr::from(3u64)); - // assert_eq!(lagrange_coeffs[3], Fr::from(4u64)); - // } + #[test] + fn test_lagrange_coeffs() { + let poly = BivariatePolynomial::new( + vec![ + Fr::from(1u64), + Fr::from(2u64), + Fr::from(3u64), + Fr::from(4u64), + Fr::from(5u64), + Fr::from(6u64), + Fr::from(7u64), + Fr::from(8u64), + ], + 2, + 4, + ); + + let lagrange_coeffs = poly.lagrange_coeffs(); + + // From sage script + // poly_lag_coeff = [ + // 0x0000000000000000000000000000000000000000000000000000000000000024, + // 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffffd, + // 0x00000000000000059e26bcea0d48bac65a4e1a8be2302529067f891b047e4e50, + // 0x0000000000000000000000000000000000000000000000000000000000000000, + // 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff9, + // 0x0000000000000000000000000000000000000000000000000000000000000000, + // 0x30644e72e131a0241a2988cc74389d96cde5cdbc97894b683d626c78eb81b1a1, + // 0x0000000000000000000000000000000000000000000000000000000000000000] + println!("lag: {:?}", lagrange_coeffs); + assert_eq!(lagrange_coeffs.len(), 8); + assert_eq!( + format!("{:?}", lagrange_coeffs[0]), + "0x0000000000000000000000000000000000000000000000000000000000000024" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[1]), + "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffffd" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[2]), + "0x00000000000000059e26bcea0d48bac65a4e1a8be2302529067f891b047e4e50" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[3]), + "0x0000000000000000000000000000000000000000000000000000000000000000" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[4]), + "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff9" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[5]), + "0x0000000000000000000000000000000000000000000000000000000000000000" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[6]), + "0x30644e72e131a0241a2988cc74389d96cde5cdbc97894b683d626c78eb81b1a1" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[7]), + "0x0000000000000000000000000000000000000000000000000000000000000000" + ); + } } diff --git a/bi-kzg/src/structs.rs b/bi-kzg/src/structs.rs index 745bcec1..f6f2999e 100644 --- a/bi-kzg/src/structs.rs +++ b/bi-kzg/src/structs.rs @@ -30,8 +30,8 @@ pub struct BiKZGSRS { /// ..., g_1^{\tau_0^N\tau_1^M} /// ) pub powers_of_g: Vec, - // /// g in lagrange form over omega_0 - // pub powers_of_tau_0: Vec, + /// g in lagrange form over omega_0 + pub f_x_b_scalars: Vec, /// g in lagrange form over omega_0 and omega_1 pub powers_of_g_lagrange_over_both_roots: Vec, /// The generator of G2. @@ -78,8 +78,8 @@ pub struct BiKZGProof { pub pi1: E::G1Affine, } -impl From> for BiKZGVerifierParam { - fn from(srs: BiKZGSRS) -> Self { +impl From<&BiKZGSRS> for BiKZGVerifierParam { + fn from(srs: &BiKZGSRS) -> Self { Self { g: srs.powers_of_g[0], h: srs.h, diff --git a/bi-kzg/src/tests.rs b/bi-kzg/src/tests.rs index f6193c03..5f881c68 100644 --- a/bi-kzg/src/tests.rs +++ b/bi-kzg/src/tests.rs @@ -1,9 +1,12 @@ use ark_std::test_rng; -use halo2curves::bn256::{Bn256, Fr}; +use halo2curves::{ + bn256::{Bn256, Fr}, + ff::Field, +}; use crate::{ bi_kzg::BiKZG, pcs::PolynomialCommitmentScheme, poly::lagrange_coefficients, - util::tensor_product_parallel, BivariatePolynomial, + util::tensor_product_parallel, BiKZGVerifierParam, BivariatePolynomial, }; #[test] @@ -12,7 +15,7 @@ fn test_bi_kzg_e2e() { let n = 2; let m = 4; let srs = BiKZG::::gen_srs_for_testing(&mut rng, n, m); - + let vk = BiKZGVerifierParam::::from(&srs); let poly = BivariatePolynomial::new( vec![ Fr::from(1u64), @@ -39,15 +42,25 @@ fn test_bi_kzg_e2e() { let commit = BiKZG::::commit(&srs, &poly); let (proof, eval) = BiKZG::::open(&srs, &poly, &(x, y)); - assert!(BiKZG::::verify( - &srs.into(), - &commit, - &(x, y), - &eval, - &proof - )); + assert!(BiKZG::::verify(&vk, &commit, &(x, y), &eval, &proof)); + + for n in [2, 4, 8, 16] { + for m in [2, 4, 8, 16] { + println!("m: {}, n: {}", m, n); + let srs = BiKZG::::gen_srs_for_testing(&mut rng, n, m); + let vk = BiKZGVerifierParam::::from(&srs); + for _ in 0..10 { + let poly = BivariatePolynomial::::random(&mut rng, n, m); + + let x = Fr::random(&mut rng); + let y = Fr::random(&mut rng); - assert!(false) + let commit = BiKZG::::commit(&srs, &poly); + let (proof, eval) = BiKZG::::open(&srs, &poly, &(x, y)); + assert!(BiKZG::::verify(&vk, &commit, &(x, y), &eval, &proof)); + } + } + } } #[test] From df2485e534b25fad62ddd7e64455bf225314f4e0 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Thu, 13 Jun 2024 22:23:47 -0400 Subject: [PATCH 17/31] fix bug --- bi-kzg/1.log | 404 +++++++++++++++++++++++++++++++++++- bi-kzg/script/lagrange.sage | 15 +- bi-kzg/src/bi_kzg.rs | 23 +- 3 files changed, 426 insertions(+), 16 deletions(-) diff --git a/bi-kzg/1.log b/bi-kzg/1.log index 92e101d4..443ac0ed 100644 --- a/bi-kzg/1.log +++ b/bi-kzg/1.log @@ -10,21 +10,411 @@ omega 1: 0x30644e72e131a029048b6e193fd841045cea24f6fd736bec231204708f703636 n: 2 m: 4 start to compute the scalars -lagrange_tau_0: [0x0000000000000000000000000000000000000000000000000000000000000003, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff] -lagrange_tau_1: [0x0000000000000000000000000000000000000000000000000000000000000064, 0x30644e72e1319feebbb9861cf605af3a73ffd18bb2bfea627fa6d5f840d1c959, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffb6, 0x000000000000003afc96bf998b7ba922b43416bcc6f9862ec43b1f9baf2e3690] +f_x_b_scalars: [0x00000000000000000000000000000000000000000000000000000000000004b0, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffce1] lagrange scalars: [0x000000000000000000000000000000000000000000000000000000000000012c, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff39, 0x30644e72e1319f78c28c06e9df0e5cf50b97a41224ccde04f73096c0e2755c09, 0x0000000000000075f92d7f3316f7524568682d798df30c5d88763f375e5c6d50, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff20, 0x0000000000000000000000000000000000000000000000000000000000000096, 0x00000000000000b0f5c43ecca272fb681c9c443654ec928c4cb15ed30d8aa3b0, 0x30644e72e1319fb3bf22c6836a8a0617bfcbbaceebc66433bb6bb65c91a392e1] start to compute the affine bases start to compute the lagrange bases lagrange scalars: [0x000000000000000000000000000000000000000000000000000000000000012c, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff39, 0x30644e72e1319f78c28c06e9df0e5cf50b97a41224ccde04f73096c0e2755c09, 0x0000000000000075f92d7f3316f7524568682d798df30c5d88763f375e5c6d50, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff20, 0x0000000000000000000000000000000000000000000000000000000000000096, 0x00000000000000b0f5c43ecca272fb681c9c443654ec928c4cb15ed30d8aa3b0, 0x30644e72e1319fb3bf22c6836a8a0617bfcbbaceebc66433bb6bb65c91a392e1] -thread 'tests::test_bi_kzg_e2e' panicked at bi-kzg/src/tests.rs:55:5: -assertion `left == right` failed - left: 0x0000000000000000000000000000000000000000000000000000000000014d3d - right: 0x0000000000000000000000000000000000000000000000000000000000002d29 +poly lag coeff: [0x0000000000000000000000000000000000000000000000000000000000000024, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffffd, 0x00000000000000059e26bcea0d48bac65a4e1a8be2302529067f891b047e4e50, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff9, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x30644e72e131a0241a2988cc74389d96cde5cdbc97894b683d626c78eb81b1a1, 0x0000000000000000000000000000000000000000000000000000000000000000] +finished commit +poly: BivariatePolynomial { coefficients: [0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000003, 0x0000000000000000000000000000000000000000000000000000000000000004, 0x0000000000000000000000000000000000000000000000000000000000000005, 0x0000000000000000000000000000000000000000000000000000000000000006, 0x0000000000000000000000000000000000000000000000000000000000000007, 0x0000000000000000000000000000000000000000000000000000000000000008], degree_0: 2, degree_1: 4 } +point: (0x0000000000000000000000000000000000000000000000000000000000000009, 0x000000000000000000000000000000000000000000000000000000000000000a) +f_x_b: [0x0000000000000000000000000000000000000000000000000000000000001d6b, 0x00000000000000000000000000000000000000000000000000000000000021c2] +q_0_x_b: [0x00000000000000000000000000000000000000000000000000000000000021c2, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x0000000000000000000000000000000000000000000000000000000000000009 0x000000000000000000000000000000000000000000000000000000000000000a +here2 +res: true +m: 2, n: 2 +omega 0: 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000 +omega 1: 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000 +n: 2 +m: 2 +start to compute the scalars +f_x_b_scalars: [0x0000000000000000000000000000000000000000000000000000000000000018, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff1] +lagrange scalars: [0x000000000000000000000000000000000000000000000000000000000000000c, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff9, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff8, 0x0000000000000000000000000000000000000000000000000000000000000006] +start to compute the affine bases +start to compute the lagrange bases +lagrange scalars: [0x000000000000000000000000000000000000000000000000000000000000000c, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff9, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff8, 0x0000000000000000000000000000000000000000000000000000000000000006] +finished commit +poly: BivariatePolynomial { coefficients: [0x28529920e40112fe2e9d58c0db300a98ad3d5231b5e69e8adf414654474a982b, 0x01ea7f4579ced4124c477515e0f2de62da874c3ec078b59912b98dba52ed7853, 0x1a6124422f756ba9e16761c1d95d295a2b14267f1266f04d91a603466934532a, 0x16f7715e31ed1c4c4b910916fb0d4b41457cd7580d187742d8afebaddb4cd73b], degree_0: 2, degree_1: 2 } +point: (0x292e552a4945289f77eeabb9cd9caaa98caec50805b10b6d5c5a7b5a302252f3, 0x1c8603896a992e6063e301fd68eaa34780850235549b590b3cff365c58a0568d) +f_x_b: [0x04b6dad76a64c12a220c3c0832d51fdeb7cd7fd17798dd080842731639e4f849, 0x224af4b667ed288ee97b44d76add61c46e4be3bd934df9ad21c55b0d2e8d8b62] +q_0_x_b: [0x224af4b667ed288ee97b44d76add61c46e4be3bd934df9ad21c55b0d2e8d8b62, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x292e552a4945289f77eeabb9cd9caaa98caec50805b10b6d5c5a7b5a302252f3 0x1c8603896a992e6063e301fd68eaa34780850235549b590b3cff365c58a0568d +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x0e82cc355069b60a7ccf99b9154107826b75751f88ddbd1e07d69fbddaceff3b, 0x082e61c11f858d95cad2cc66e141c97998d679fedd1c784e19f09596b0646989, 0x0896062fad6c3cabff665b3b9de75306ea6217c38841b479988c7428a3943e4b, 0x07126d3e656fc3fc22c108056eccb6d55ee931e2c86055e096be9210988f71a1], degree_0: 2, degree_1: 2 } +point: (0x151956dca0bab6306d06fee3a08f916470b6fc0f5d284fb2e58891f8d4dfb4d6, 0x26bd54d45efd19ff17533e99cf70209627f2c342e4e2aab664ea3d52cd44c32a) +f_x_b: [0x152134071879cc123b24dc146283f106de447282132e8d8e8aa5c0850531778d, 0x196b4b11b62e9528b9911d042f7d6ea3186ee87bb699365b806af320a27c6573] +q_0_x_b: [0x196b4b11b62e9528b9911d042f7d6ea3186ee87bb699365b806af320a27c6573, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x151956dca0bab6306d06fee3a08f916470b6fc0f5d284fb2e58891f8d4dfb4d6 0x26bd54d45efd19ff17533e99cf70209627f2c342e4e2aab664ea3d52cd44c32a +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x031df8a22d2f9c1168f02a9c9c343334586ce820147711e918c16ce9e372115d, 0x11e48d19c1365c51686d2df7086e59158f78275b9f5a39f0c9886baebd345afa, 0x2f0a41e02aee0467a1e41d95677e26136e4c8dc0973d93211fdb4ee4d3884bba, 0x182caea2e22bbfa372f5f1ac6594484344ee3c4c1b3ff547d1b5b1bbdf3820ac], degree_0: 2, degree_1: 2 } +point: (0x0b82797c2e7a97dd307c4af3fd386fdac96cd7d1ba745a325c0b1c3db9a6c890, 0x114c0145a86181a3f83748ba901316c4fc752112080d081c80b704fdb0f25d74) +f_x_b: [0x0a565042f563c2e3e28b43cb99a5f31d57603d8606289d8635733fa2c55975e0, 0x05e4ad539f5fb22a26f2b0c3c81e34748308f8eb5242b6eb34e4414adc9c8e03] +q_0_x_b: [0x05e4ad539f5fb22a26f2b0c3c81e34748308f8eb5242b6eb34e4414adc9c8e03, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x0b82797c2e7a97dd307c4af3fd386fdac96cd7d1ba745a325c0b1c3db9a6c890 0x114c0145a86181a3f83748ba901316c4fc752112080d081c80b704fdb0f25d74 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x136ddb1c61e5d4d246f571a1ed2d78e64d6c074f7e93733f95599b33644df7ea, 0x04492380d843c40545dd3100066314d10743769b3be9274853f5ec58c0db1a9c, 0x2c89839003fb91afaed6507e07b899f15e28775c8609bc272ea2f6da0edb9f18, 0x1d0ff87b13d7e9ecc80eb284d8c776a5a1d4dc861aa3c18513a839bb230d5b63], degree_0: 2, degree_1: 2 } +point: (0x005d82805494b3c3fbcef176e48ca0227fe082aff6fcb847be30c4e00334cde6, 0x2ac47771fc4a8f19f6f17db67fe170bcfc944af8620d4a253a5c4f138d449c79) +f_x_b: [0x14de3b150b3fa45e7177abbb3eb55eae7119543dcfa2ecca0192e21b0b792d35, 0x187aa1946c0013d0e32833b9a57b9a0d55eaea6d56ca8f2b6bdf24bdc4c82c8d] +q_0_x_b: [0x187aa1946c0013d0e32833b9a57b9a0d55eaea6d56ca8f2b6bdf24bdc4c82c8d, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x005d82805494b3c3fbcef176e48ca0227fe082aff6fcb847be30c4e00334cde6 0x2ac47771fc4a8f19f6f17db67fe170bcfc944af8620d4a253a5c4f138d449c79 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x1bbe64bf201e36337b37164817708b1ec8186718f87f6579f7f02cb2c22ee38b, 0x1b37374da26a3a0b9c707c492d214a22717c51ea143616310a7517b5eb4c80e7, 0x19fdc820bdd8193f88e3dac5fabb2b923bedaa88c983839d12a7a728987ecf29, 0x27ca00dfcf1ecc882023ad7bab845d2f70478e51b4ff15a633c86db03b6d762b], degree_0: 2, degree_1: 2 } +point: (0x0415e4367921908bfa498d497b8a176f5ff755d750fa1de26d5360e014eaec43, 0x19da74ab07ad91055e5d984af7914a32a52d05ed9feeeac5ba69aa9ffb45a708) +f_x_b: [0x22addd03640c5a86c0f26e3cee4f40981f0e573d0e600a58082768ef7cd0829b, 0x191a608fe6c134c56fe2047b4bc43f3431fda751eb4b4cd2d34d4eeecc5ae537] +q_0_x_b: [0x191a608fe6c134c56fe2047b4bc43f3431fda751eb4b4cd2d34d4eeecc5ae537, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x0415e4367921908bfa498d497b8a176f5ff755d750fa1de26d5360e014eaec43 0x19da74ab07ad91055e5d984af7914a32a52d05ed9feeeac5ba69aa9ffb45a708 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x0b8fc6c1e14bb35e2a1d7885c2338514ed95d83b177a08fc6eb23f23d311a1f7, 0x0df9d50ed9f841e70b00a70163588b180dde0648de4b5f43d74964ae235f884e, 0x1d7fc0ca88e60d38fb0e49ee50cb63551d51359896fd5fea6f9243372db2da22, 0x0c3c57a5dc6da870646fc519919b89faee66077b1dbb85ac753d0e761e0a6c6c], degree_0: 2, degree_1: 2 } +point: (0x1162a28d882117feca6126fce44365d987b37ae52822142626198b740af416ad, 0x172db215c90780c364f6b3d54013d39f1c9ebb9e046f6911a84e059a370c1c8d) +f_x_b: [0x213ae76092e2c685adb84495b6a9413fa36ff983aa25f888b07683bd8893cddf, 0x13cd08f138ef0c5138aabacabd373fbffe0866403de2544a85b51c7d274b319f] +q_0_x_b: [0x13cd08f138ef0c5138aabacabd373fbffe0866403de2544a85b51c7d274b319f, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x1162a28d882117feca6126fce44365d987b37ae52822142626198b740af416ad 0x172db215c90780c364f6b3d54013d39f1c9ebb9e046f6911a84e059a370c1c8d +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x2133fc92389e143749df33c69863b635ee37de497343aebb47ab96fe4df2c228, 0x21b7d97511b224719bc16f0eb8825660849f8cc1958743515f0adfd674aeb4e4, 0x00543c11ad2b2bc9eb3874b4f83b4b67c1700216a620f23ce7a652a79e2bd05b, 0x2bd9af20c1d34e5bc3f06d091fd3dfadc413ed5926bbf457f9c7b9f91d28ca62], degree_0: 2, degree_1: 2 } +point: (0x2d250b31f0af7167fbb9ee5bda8f3b519fd2c400bcea759d0e780353121ec514, 0x01f3f20c8aa0c397f72d34d16ac09e2d5a0bb06bbfc2621d5766604969780c3f) +f_x_b: [0x18e7a9a70a24c9d207cb79fc1f609e756b659234afc995cfcb373ea96380a40c, 0x1b0f353d6d50f4b86139a5faf0bb0ea55387a7f8ec7ce3981f8541c5343a1566] +q_0_x_b: [0x1b0f353d6d50f4b86139a5faf0bb0ea55387a7f8ec7ce3981f8541c5343a1566, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x2d250b31f0af7167fbb9ee5bda8f3b519fd2c400bcea759d0e780353121ec514 0x01f3f20c8aa0c397f72d34d16ac09e2d5a0bb06bbfc2621d5766604969780c3f +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x172412359106e3433cb2434c0f37e10adcc27e741f7ea8384a8c8f70510cd72c, 0x2ec6af4f75e83641d4336d6eccfde558ca886a761111bd489bd555678b5ce9c3, 0x176878d232207eec8be262ceb970bf5c690346f6175dcb6d2193d15526529165, 0x22e5004514ec403917bc1acd85af83aae773247991872fdd299e9cc703d7ccda], degree_0: 2, degree_1: 2 } +point: (0x1f613dac90f9f2639d877d7866f30f62795f2f23a7b2710827c6bb80a804bed6, 0x1e402abf7cd6960b5538a4ae1e14f2fcb383a4ac413ef191c231b7aa5e841047) +f_x_b: [0x19ff6ece138e7b8e49c8fee5946d91cf91fa3fbd84fb63328aeb4a373cc3be87, 0x0fcae70e1fb3b03399cfb7c8cd83adce26bd5ac8b80019e4f5fa4d9b48ed2252] +q_0_x_b: [0x0fcae70e1fb3b03399cfb7c8cd83adce26bd5ac8b80019e4f5fa4d9b48ed2252, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x1f613dac90f9f2639d877d7866f30f62795f2f23a7b2710827c6bb80a804bed6 0x1e402abf7cd6960b5538a4ae1e14f2fcb383a4ac413ef191c231b7aa5e841047 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x13703c6d8902ba2db2e3ffa3beb77aa60fe80aa7b35a56cc95a859fb06f25386, 0x13631fb9023e6d9b76798a9b33b678064f07d2bbde1e6f3d26f1a6a73036a2a9, 0x041cf8010644cda62d5b7b917e57aa04e91d6a05fad2d8b0c349e5b0248087aa, 0x28c85887e02a4aa3dfb71c917efdc3035af7efeaa0f54854cffc1cfdaf39b992], degree_0: 2, degree_1: 2 } +point: (0x0c8e1daa01383e7da069758dbd90f1ab05f7d9f56e1dd0e586f963af61cc1af3, 0x09ecd5a6c3cc9083f93758733722251ad730a12c3e52696c345325fb566f219c) +f_x_b: [0x22cf20b8785f15b10635f6b33a313b774c2b72824d0c0df4f366db9ac70e06a2, 0x002702c6de401a78485ca3b316cbe2642f2855cd658c6dd95e3cd8307fc745e3] +q_0_x_b: [0x002702c6de401a78485ca3b316cbe2642f2855cd658c6dd95e3cd8307fc745e3, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x0c8e1daa01383e7da069758dbd90f1ab05f7d9f56e1dd0e586f963af61cc1af3 0x09ecd5a6c3cc9083f93758733722251ad730a12c3e52696c345325fb566f219c +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x2d66bb0e3ec7085598e0b253d89cccd6c0d0132f53f3560cd2b93106a6c896be, 0x116b4afb036ab74dba2713e9d26976ea38d0a2ae2bef45ba9dc56feffff28511, 0x1cabad80e674607bd69620c156e3764e8b7091c94d919eb2d63aae4ea1a1810d, 0x11329b11af9cf77998ad2e329762dded99806f1d2c883abd254f6f0a1e90b765], degree_0: 2, degree_1: 2 } +point: (0x12bde00976700c254b4d94bf42cdba0aa19c89a13261ed3a186a2ba2de0c24aa, 0x1831d67f1931bc74751fdbf6a26d36f095e2a70dffbd6fc33b6c1fb97c3a60cd) +f_x_b: [0x17eb9a41733d35f102c68e68f81ff9953bbc88985839bdf8bf5ca14cefdfedf3, 0x0d895abd38ab978ed29ac28320e604954ebd43faa73502720d2c9aa932dc3a02] +q_0_x_b: [0x0d895abd38ab978ed29ac28320e604954ebd43faa73502720d2c9aa932dc3a02, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x12bde00976700c254b4d94bf42cdba0aa19c89a13261ed3a186a2ba2de0c24aa 0x1831d67f1931bc74751fdbf6a26d36f095e2a70dffbd6fc33b6c1fb97c3a60cd +here2 +res: true +m: 4, n: 2 +omega 0: 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000 +omega 1: 0x30644e72e131a029048b6e193fd841045cea24f6fd736bec231204708f703636 +n: 2 +m: 4 +start to compute the scalars +f_x_b_scalars: [0x00000000000000000000000000000000000000000000000000000000000004b0, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffce1] +lagrange scalars: [0x000000000000000000000000000000000000000000000000000000000000012c, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff39, 0x30644e72e1319f78c28c06e9df0e5cf50b97a41224ccde04f73096c0e2755c09, 0x0000000000000075f92d7f3316f7524568682d798df30c5d88763f375e5c6d50, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff20, 0x0000000000000000000000000000000000000000000000000000000000000096, 0x00000000000000b0f5c43ecca272fb681c9c443654ec928c4cb15ed30d8aa3b0, 0x30644e72e1319fb3bf22c6836a8a0617bfcbbaceebc66433bb6bb65c91a392e1] +start to compute the affine bases +start to compute the lagrange bases +lagrange scalars: [0x000000000000000000000000000000000000000000000000000000000000012c, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff39, 0x30644e72e1319f78c28c06e9df0e5cf50b97a41224ccde04f73096c0e2755c09, 0x0000000000000075f92d7f3316f7524568682d798df30c5d88763f375e5c6d50, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff20, 0x0000000000000000000000000000000000000000000000000000000000000096, 0x00000000000000b0f5c43ecca272fb681c9c443654ec928c4cb15ed30d8aa3b0, 0x30644e72e1319fb3bf22c6836a8a0617bfcbbaceebc66433bb6bb65c91a392e1] +finished commit +poly: BivariatePolynomial { coefficients: [0x11c7e0e35e67d2828d28120fabcce980fdba8d58c1212bc0868bde8a084de9dd, 0x01c0c488bd03681c55098a7868aaaec94cfd1779c90de238a988c0d0399d0ada, 0x2c0bafa9dff55a23a67a81b6eb2c04dc4c719bb2deee00125b58089128ba7315, 0x2c99d65965843b34f978f316e6632a9a47e87e7cf0055ca728c0a674d3c380c6, 0x0a9f1f3f3378e25fcf7a814c0dc30f660481c6f0fcc207361ff06f3c91f29251, 0x03a77999bec9ab4ed4ea6fcfc29c66e999d51f32be0ccd02fff0241d8f30e04e, 0x2b2d14dcb2cb1336d8245fd5c41c315741bc79bf85da6fdbb1452fc91af120f4, 0x10b23cfa73f5659038976f93035a5222d7a5ece9f5f78f8b87f433df1eb445ea], degree_0: 2, degree_1: 4 } +point: (0x13be5805568b552a932b2b7a5cb7933f2db351b21998e67930418f4059e3fd31, 0x22f811b162a994df97f0a146cab2a27146d6dc8706c906f432102611ed6ba97a) +f_x_b: [0x0f52a6364d703a9bab1ad1165cfb946a4c7848cd8873e2fe57a02fbdafbb1882, 0x2be43aea9602b9371e49708e0ecaab958359816e03a549aaaaf06346119aee61] +q_0_x_b: [0x2be43aea9602b9371e49708e0ecaab958359816e03a549aaaaf06346119aee61, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x13be5805568b552a932b2b7a5cb7933f2db351b21998e67930418f4059e3fd31 0x22f811b162a994df97f0a146cab2a27146d6dc8706c906f432102611ed6ba97a +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x2a62b49cc9b4b54e496f3025bb47877b1a0d303d18d284840169c57e6c5337a4, 0x0101bd6111aea9671f80d0d278eeb30953a4ffa8056c2700e6d8da90247bda11, 0x29e57399e473c2c00c0536b27d0cc51b28d6e340f1c4472c4b7493daf1f5d8b4, 0x2bf669c024f457a9214c9d915601123ab0d28a839b09c8e13627716ef5c800c6, 0x08df965406a43ea3e5150df888e0997d6bf05b6e8d283a46f08589da52cdb081, 0x23e5695daff42298d80c7168d0a69fb5f78fe4ea05bab9e0bc15c0bf8111c52f, 0x22d36548a3b0a8f731cf917009cdce7298a7870bd183ba63a1985169c86719b4, 0x2d6ee202e5311f5bdd62ea4a570f8f504514a4f9de16b4c9061462f3158f3750], degree_0: 2, degree_1: 4 } +point: (0x1baf2028415add9831d922e5778bafc6183a56ca78cf5f881992470fa4571df2, 0x1db796a9b4dd6543979cd69d85762bd80856503b29551de3069994411c548692) +f_x_b: [0x0d38c5405d15edce2969a0356e87b5f15deaf04628e7f976a3c809de1519f5c7, 0x06895dc1df9108729df28144f7be2ebe9048f5bc5336451ae577acc156676551] +q_0_x_b: [0x06895dc1df9108729df28144f7be2ebe9048f5bc5336451ae577acc156676551, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x1baf2028415add9831d922e5778bafc6183a56ca78cf5f881992470fa4571df2 0x1db796a9b4dd6543979cd69d85762bd80856503b29551de3069994411c548692 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x04f297af9b2cd89b11eb6bbc0b8dd27f3b73680e058a9470d5718ed4b5532094, 0x25a6033c31e5e828a56ed6323e6709732350dd3c57661ef3f2bdbb23c510fc91, 0x1fee75cec3cb52e078ed2bdbe8da6131dbb4a5238d6b6dd10fc84f9cb2c1b959, 0x05e37e452061da5d289d44b8153b46b9069ab1dfc938791a24b9671189feeeaf, 0x0797d6753438b249dc553c460cd87fd3d910e8670cb94c8b94ca030468be5f61, 0x0dd2d750461d588473fc872882a456adc5757d118305f62346ce73a32bc579d0, 0x0909545e9bb9985fc8e78f4e72041c9747bfc82baf23bb1c074b96faeec0208c, 0x2b9e9dc1d047dedb159b224aef4cdb0d71c6fd19f73a356e4f811442eddb446c], degree_0: 2, degree_1: 4 } +point: (0x19a479d3ce4ab407099bc8cd68b689e33bdd7bbe4593cb163f7af1108a970c30, 0x2f2331603c17c7c0e0b66a4f50f088e3cbc3560d64b8a42a5dba9628046831b6) +f_x_b: [0x270957b44cdd23d985ab7263ab89f489958ab0f68447c75287a5d2fc32458f44, 0x01876e0f41917ff0a9247b2ebef35e021adbafb582f9303aa9cef471cbd10a6f] +q_0_x_b: [0x01876e0f41917ff0a9247b2ebef35e021adbafb582f9303aa9cef471cbd10a6f, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x19a479d3ce4ab407099bc8cd68b689e33bdd7bbe4593cb163f7af1108a970c30 0x2f2331603c17c7c0e0b66a4f50f088e3cbc3560d64b8a42a5dba9628046831b6 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x1547b7b863825dea8170d012837ebe218ef15a1664152f625af07ddc1cb8f7a2, 0x17f93f74519569559404f7ea10b620e0bd742ea6fce901192789bf61bda91879, 0x02d04b1de0c0a79db0f9e36a9efdf1d4b065bcc60ef309a070be752c53be7f6f, 0x163f4165230cfae0294b3f765a3ab61c6d92f6b8ad39beff29ae2de9171a84d3, 0x016452d89eca22e34f22de18b1f839513501b1096e72861f6d711168eaacf964, 0x0a36fa057199699a8d93d2c76dec84eb358faec2b1a831f9d418ea4e0532245e, 0x0883b2c7cefd49e2367bae89f76ce8be70fcdb827f41e9d332a2f8e91764325e, 0x29da4281d56be059705e6638e9ed295d7830a680878b2471c8f8baeb3cbe1c28], degree_0: 2, degree_1: 4 } +point: (0x1a7b6aebeb2048555b9c922ffdac0ee626d19a94c408e6550b69c5bb38bba214, 0x25216819a7d1e8284be43aa7b00d6aa42209c858ddbc7c053a1304d0ee1ba68a) +f_x_b: [0x282d4a7571e78eee01d6724b22a2401eef846b5b35fa93e48dd05be52d818122, 0x11e45d8696d912949ea8fdb2f3d71679e31e401b39093682204ce37e5f324d62] +q_0_x_b: [0x11e45d8696d912949ea8fdb2f3d71679e31e401b39093682204ce37e5f324d62, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x1a7b6aebeb2048555b9c922ffdac0ee626d19a94c408e6550b69c5bb38bba214 0x25216819a7d1e8284be43aa7b00d6aa42209c858ddbc7c053a1304d0ee1ba68a +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x08f1bfcba4ac26a07c4fcaee1e4d858452b4329060b7b8cad9dcc85cff3ad983, 0x001e0893b7ee1e08c937ed05b6a55bc89e75df0ab66c9324a2639e0d5385c9ea, 0x042b78728556911fe7848262031b4ff833b10375918f30ac674e4b1902dafe34, 0x066fbd2fc079b7c6079bee88fd6f82c8c6de0dc995b500e828f040d6a4d839a0, 0x03b2f6e1e31f860b883d35d77c5086f4d17ea93a7d7cab6a52618eb1fb4eb3f5, 0x2f607d7262220b5b78dd08668e4303e9c37abe8e85c655b00f2a629d0b461042, 0x0d984f2f83db8f03720ca31338e8d1f5fd3a203dd30164a5f123d31a52192239, 0x1ea202e7bb52a58976991788a3cd92273dc79f8c8b4e52382b83fa5d71916197], degree_0: 2, degree_1: 4 } +point: (0x1da88ccb70fd3c2c5efe5c6ded48545c828fe6b73b8e1c2a3b1c32af3e72d78d, 0x052c1d7f0b50a353bcd47abf8a00fee17824efbdffe0f2779d051607cc8a1d2a) +f_x_b: [0x29384a10fa9d7f13c472f373cb2969b67b355cec8281a8d07e33a3b9d470d68e, 0x07c5c565353d2b226e873378de2ecd9e3c1289ac2a075f7e00dcee4102998729] +q_0_x_b: [0x07c5c565353d2b226e873378de2ecd9e3c1289ac2a075f7e00dcee4102998729, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x1da88ccb70fd3c2c5efe5c6ded48545c828fe6b73b8e1c2a3b1c32af3e72d78d 0x052c1d7f0b50a353bcd47abf8a00fee17824efbdffe0f2779d051607cc8a1d2a +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x203897642af395a09433e03fbf8bca17c57c250951ba2bcf9686e991189a4a79, 0x21a161a5b62a3be76ecae44ffb92b422135039cb04f2668a4441d10db25ed5fc, 0x0dd66d8c0eea90daa3248a2d6711f1a23cb2d54de7247fe8cb69c6033e8689c1, 0x0e082aa6c2773bac642483865590488c00d04661e047ad7389174de9e0dbe35e, 0x0caf3795e7210e5feaa6145bd919b18b41ae4a2b2feeccc1e8c002687a1d1ae8, 0x108d05451d92b30bf67bb741e2f858e103fe55de124ea07a40ce90cfc42bcde9, 0x286de8652d1c70ba5785027bceeb8513dff18d4463476a2a819f493e66e2a92c, 0x053e864e5472e5962fa2e7e6d0f8473a8a19c7a136741ba85b4dc5098aac927d], degree_0: 2, degree_1: 4 } +point: (0x1e4703528a10e133cb501890ba07d24208a9e80d557fe6656098fbdb0ff6d074, 0x2a1f90c8f296f02d40d1c6840ab34865b22f948e991470f2accf5648c860e474) +f_x_b: [0x1d62683289b6dd5d750de86dde45fcbcccee1fd50545af71d569fad4c6f19861, 0x1ec0889bd1a69905675d0d7f1e46a9ccebb403149f06401dcc25495a11085d5c] +q_0_x_b: [0x1ec0889bd1a69905675d0d7f1e46a9ccebb403149f06401dcc25495a11085d5c, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x1e4703528a10e133cb501890ba07d24208a9e80d557fe6656098fbdb0ff6d074 0x2a1f90c8f296f02d40d1c6840ab34865b22f948e991470f2accf5648c860e474 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x2556b0eeccc865299a8eb34a72e40b538fca319c7eb00701b931291f1ad38889, 0x1f361a735bfdba3a230187b75f4d63a6860f944477ff9bebd12be0dee9b51ee6, 0x14cae644f7d8306f54145e074533df5f803244b5bb0b7008b9e69f467c123a17, 0x2c0d31f26758b90fb0008276f22d2b73a25ea0ab291906ae63854c9ea6affb03, 0x069665e6ddad58178aa9a8c9767a742b5896589f862ce1d6c73ea3bea3325b8b, 0x080cb3ac3afbbb5a33ff4447fddc0c66610afa494080bc2a9946bcb7e42de2b2, 0x1bc08e760c77292cd2587c433dbabf9314c39bb0777ea7314353514fcfcbef43, 0x11802ed77cecfbc35e142e1193cef3099a8cf2605352c6f50634950706679ad4], degree_0: 2, degree_1: 4 } +point: (0x2308143aeeb22f2825d94be2f10b7f33d6e04c491463dc8e0730d0fb0e90d716, 0x1eb5defff77731546059fc980a757ae3541ec52719d8e60003e3eae134e441ed) +f_x_b: [0x04f336a9837427a936781aa06591ee2ea3c36b3874d361fdd7788a78d707eaa4, 0x220a3757113ef0f19b94f7d1e48114f6081f3e83d35d52cdee88061889bfdc62] +q_0_x_b: [0x220a3757113ef0f19b94f7d1e48114f6081f3e83d35d52cdee88061889bfdc62, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x2308143aeeb22f2825d94be2f10b7f33d6e04c491463dc8e0730d0fb0e90d716 0x1eb5defff77731546059fc980a757ae3541ec52719d8e60003e3eae134e441ed +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x00ca9d4b100fcda63cd87ca2069cc82c1efbe6a99dbb24c0b89ad1a4e557cd01, 0x04edd151f98c7747e883c3298a6f5a5304d01c46c62645b161f10f77735a08de, 0x207601dd751d317d63b41af27fdce89d1a4caf730e5c5da8bf1e5e7fde409357, 0x19d1d5700a32a0af51eb3156bdeeaa0534491c55ecb7ddb96f2d4a6846c1266b, 0x0ee89ae37cae337dc15ac5c93b3655990fbdd9fd0201e50c551c4074ddcf0a75, 0x01cfe0e7deff5ee54edecbea25a2152d78e2aeb053be5ea37e90fe87f9fed8c3, 0x114ad7c4f05d45639bc644f21f9d4f6624c52b32044e1bccc7e7e7b49547712a, 0x17f2af8cfed28389e13fac4c49a027898147673e38eace631220085f556009e7], degree_0: 2, degree_1: 4 } +point: (0x0f11d3931b653f6c66128ae784736109c7373f3df832e1c3e73a15eba16055da, 0x11eee38223b9f99e99158decaf3b24cec7fb57f7d806eb06035db22e2d254319) +f_x_b: [0x17c1db658dcad482d2f2c3cdddd9f07a4c32fbb8225a81ea4fb24a7a2f767dcd, 0x28215ad67c1d13a948cd7a892fcab74986d137039533e3931b3f05c1e8a43624] +q_0_x_b: [0x28215ad67c1d13a948cd7a892fcab74986d137039533e3931b3f05c1e8a43624, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x0f11d3931b653f6c66128ae784736109c7373f3df832e1c3e73a15eba16055da 0x11eee38223b9f99e99158decaf3b24cec7fb57f7d806eb06035db22e2d254319 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x274b5c5ae0a18408778083c325dd9291159071f10897c228513eab99f7d98e91, 0x1c0d35642cdd2c4a520b9ed88e8ae9289ceacdf3ff027d5c1a5908fae1bbe852, 0x0a8895c9245e7c725cbe6c955ff326183e64580f90d12bc2af801b10047671b4, 0x0cceff273af9a33d033024397e6a1e9745724dc2d7dae312551c5b4232cb06cd, 0x006661689df5f62bcb77f041a3547c09c1bd444c884e8d2d4d99245be03aa115, 0x07b014aca6ebbe51de44802833676c6ebb437db5e376452121ea213f35280f62, 0x199a7f0f90e5e5e1b4c20a207f6170e893c1e051950bf0f01159fcb269a87410, 0x1a90d9111e06f891983de59340378ea50d8a0299c689604d2dd74bd008c3d669], degree_0: 2, degree_1: 4 } +point: (0x250bfb67497dbab64e369a24361867cd1caaebb71006924733dc99fc4a5ce358, 0x24424ad46eea5b4f8ec8fcaecd2c137fd8c330a5795d2444a59b36ff4cabe4aa) +f_x_b: [0x13443e7de07239ed258f3f221f9409893d89f14e0777c5b62f744af9a0dcb71b, 0x17184ba7ac6ed3a3af7b93c90e261f0e832cd06ea67184d5dc595b532798f2ba] +q_0_x_b: [0x17184ba7ac6ed3a3af7b93c90e261f0e832cd06ea67184d5dc595b532798f2ba, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x250bfb67497dbab64e369a24361867cd1caaebb71006924733dc99fc4a5ce358 0x24424ad46eea5b4f8ec8fcaecd2c137fd8c330a5795d2444a59b36ff4cabe4aa +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x0950f093dc46787af2217ca9eb7e8b4069cbc9ca454f4dc2d189b4e259d94efb, 0x013a271da447a23c051049bec87ac532117a3c6e149057147312634b1b760027, 0x13e59d6279ac1c99ffc4f1c98be9a741af3a4902516596895d4cab834fcf73f0, 0x0c9193d2af54ed5e86a41d13cb174c2ddc7d8ce3a21e02be5abe7733f69c8c5d, 0x254269acdc1f6d4b2c40d645a29f975aa0b01b1943ed6a6e590dff350dbedb35, 0x062582f8de010472c695f2e275830f93680754e7b94c3340be2652cca2904d52, 0x180d5116c82553c6412c339e2dc625a79ea8d77406f6bc0267b99da21ab4ed78, 0x08964f38e3655651a1b71c28c5de8e7f8b64b7a722c5641c15c57ed409e1ed59], degree_0: 2, degree_1: 4 } +point: (0x1df73cce693cfde00d368e0cbc48bd35dd0ea74cce9c795baa25a84344ec224e, 0x01c620bd078515ad665ee22c6f4fb96e3280c795ab18bf29a89b0222e299f700) +f_x_b: [0x1f72a0ef1e224931c673ca148ef0ecd10138532c3566c9276d0a6af8c6129459, 0x06f446314716ffc7eb5686469c51e859d46498e8cb1a1572108aa719eaa96eb0] +q_0_x_b: [0x06f446314716ffc7eb5686469c51e859d46498e8cb1a1572108aa719eaa96eb0, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x1df73cce693cfde00d368e0cbc48bd35dd0ea74cce9c795baa25a84344ec224e 0x01c620bd078515ad665ee22c6f4fb96e3280c795ab18bf29a89b0222e299f700 +here2 +res: true +m: 8, n: 2 +omega 0: 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000 +omega 1: 0x2b337de1c8c14f22ec9b9e2f96afef3652627366f8170a0a948dad4ac1bd5e80 +n: 2 +m: 8 +start to compute the scalars +f_x_b_scalars: [0x00000000000000000000000000000000000000000000000000000000002bfb60, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efe2adc1] +lagrange scalars: [0x0000000000000000000000000000000000000000000000000000000000057f6c, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effc55b9, 0x1920ea37b9b4f882548d5327a080c198d87ce2851642edb0922feb13c551cb48, 0x1fa3b24dbab8fa7d7ff20e46c12b81f7428b5145158cd21b8d1758dc171ecdd1, 0x30644e72e12e61f8baa5a7b06413e4eeef17e5640fddec5d77c419716894c189, 0x0000000000022975fe71beaebe48f79ed0bd5742f13d02cd32be92c1af9cd450, 0x196383fe528d370a43a3f0d91e68a9665deb015f265b3d701b80a032e743e0c5, 0x1f774bc954d37b7835e2fa7b17e63cc39441e75e6027479bdc36e01cab2814d3, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effbe070, 0x000000000000000000000000000000000000000000000000000000000002bfb6, 0x1743643b277bb5b7617516c8c7ccde6d3211c37b4806270fd73265f3a72231d9, 0x10c09c25267946f6e4921f492678514aa416c3337677865648750a6adb3e8970, 0x0000000000033e30fdaa9e061d6d736e391c02e469db8433cc1ddc228769ecb0, 0x30644e72e12f76b3b9de8707c33860be57769105887c6dc4112362d240640ce1, 0x1700ca748ea55b0f76fa30a37c4c674de7ee29316ece8ef202e0f9ed8c48140c, 0x10ed02a98c5d8366d63963620378a0b4d583d4ba07474114d600a7c4427a9d4e] +start to compute the affine bases +start to compute the lagrange bases +lagrange scalars: [0x0000000000000000000000000000000000000000000000000000000000057f6c, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effc55b9, 0x1920ea37b9b4f882548d5327a080c198d87ce2851642edb0922feb13c551cb48, 0x1fa3b24dbab8fa7d7ff20e46c12b81f7428b5145158cd21b8d1758dc171ecdd1, 0x30644e72e12e61f8baa5a7b06413e4eeef17e5640fddec5d77c419716894c189, 0x0000000000022975fe71beaebe48f79ed0bd5742f13d02cd32be92c1af9cd450, 0x196383fe528d370a43a3f0d91e68a9665deb015f265b3d701b80a032e743e0c5, 0x1f774bc954d37b7835e2fa7b17e63cc39441e75e6027479bdc36e01cab2814d3, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effbe070, 0x000000000000000000000000000000000000000000000000000000000002bfb6, 0x1743643b277bb5b7617516c8c7ccde6d3211c37b4806270fd73265f3a72231d9, 0x10c09c25267946f6e4921f492678514aa416c3337677865648750a6adb3e8970, 0x0000000000033e30fdaa9e061d6d736e391c02e469db8433cc1ddc228769ecb0, 0x30644e72e12f76b3b9de8707c33860be57769105887c6dc4112362d240640ce1, 0x1700ca748ea55b0f76fa30a37c4c674de7ee29316ece8ef202e0f9ed8c48140c, 0x10ed02a98c5d8366d63963620378a0b4d583d4ba07474114d600a7c4427a9d4e] +finished commit +poly: BivariatePolynomial { coefficients: [0x18d47523833d628dc9516d2c3f2aa4a854c6819df8c81de344fca22c2d6d6a5a, 0x235093d933c2dc8e006442e40f59356584badbb0f80de985f3c2b42e63d4a3bb, 0x1b0d9e6bf24390b3485e63a706b31ed9a215fe290a614a27973922d51d54be65, 0x2c5a88f1fa81fd750ff986fa942a991fac37309277dff1bf0867f78f4398b9ef, 0x16e9ec8eca5d95526d43b0d54f033c03eebda150e0309ddf561de32b7dcecb15, 0x0ae93f600f7ed9367026cde57271e8cda342984e5233aa48381cc7fbdaf544d1, 0x001c65234ef26383d61a187d9d3ab3d633bc2aca15d69a7f5a38a6c264bc4b4a, 0x0358044477982b2335d2a93691c7e9eb2badb080603f17892fd80e906aa39e5a, 0x2d90bf41bc98ab9bc375fd7a5e1999752bfdd5fea2242e266fac3f682c119561, 0x276067fadcf23d0534c2bb548db91b13520ce49b36f073c33fc6a1f617d65c5d, 0x2c1bd47e6a7cbcaabc1fd1daf00241ef4d2834c02475b5bb1a51ba7ffc9e0606, 0x14ad94d69be972d7a8c03657554c3833107eaec022c0cd5a9b846ca05b4c68e8, 0x1d14a51b708d1573ec8cbf1a4e49ce84427b4e5a1ff5e087a714b7966ea0a114, 0x2d3e630fae3965515cd8dd1df08398169e02c94bffd5d689b2d6a1ce8a2e52d0, 0x28ca801066c9faf4b8016d5ba272d2c1033bc308fa97b94e2fe0bf67a4cabd02, 0x1f13b984d6338636462ca261d19fb0f0bd10ef770cda524519338f10765c7225], degree_0: 2, degree_1: 8 } +point: (0x19caf607494c4cec1a0c345658db3abd2c9f095336723709d9817549be1a36b6, 0x1455c594e42ea77dfc669b0591a2aa681b14642cb7109fd9d5ca711de21c3c00) +f_x_b: [0x1b140a2a80f96c77e348a782b41dd22ba2422bea833e236da391f3ca21db3540, 0x2e86a768dc7034be81dc0e42a6ac7d345d8abd145366f1a0f3a40cc96d83a214] +q_0_x_b: [0x2e86a768dc7034be81dc0e42a6ac7d345d8abd145366f1a0f3a40cc96d83a214, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x19caf607494c4cec1a0c345658db3abd2c9f095336723709d9817549be1a36b6 0x1455c594e42ea77dfc669b0591a2aa681b14642cb7109fd9d5ca711de21c3c00 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x06aaa66cd5b474208cd92424e78e41ce4c035c351cbff64e92630f81205aefa1, 0x25fe7fd17d8444fbe25cb4eb3f6f21b7e210de17c1a81d3e00afa8af9fc98535, 0x1bae1ba8c74c85713eb765b2073ac273f9bd877993f12f99430b02dc40e5e7e9, 0x1a02d6cac12d25c073ddc1c5f9328b2dc5a5658c7fc0dc9d1207c5998b98fda5, 0x03de86fdcb3fc135988e5e553f58b574cce5b84cf28ef9bd682ea2493f0b1920, 0x262090c3ad1052494f77a629145ce29e6396838bc562e738e8b62e0b7601f537, 0x0e33e288388efaec51a2d2043adebf683c33ffb673fe9c9e9c0e9f8806d92b17, 0x0bba7f59c778f13c47060fed17c30dc79558815c00ef43d2d8f8bc23ee192495, 0x059cf4141ed6afaff488856ad23ef02e160d9597a10859a79afe52d000061936, 0x2276565ce7ad7370171ccc9223b17b592d5286ec48e65162f497524e09215a5b, 0x1b36095f59f776168b8a960b60adb436dec4971ee09beb87dcd4f37a4d4da300, 0x10e1245b8bb4d6243d17e43a17e4882261e76f3f5ba68d72814f3297d0d1a3ee, 0x27941cdd90a91c6f90a8da56eb780a7f217bd0d7ef83eb5ea50c5fc3466663c6, 0x12a6193f334fe44ee97e8854cb2fe97d89fd3a849a56d7410474838edf17337c, 0x0e4b71b55f20b8f96cd38edf4d06458788067cc76a7f64594b5ea860c628e772, 0x09f765bf571693b714dd37321f6c26f7d519d2a37f9aa9e540803896b1990092], degree_0: 2, degree_1: 8 } +point: (0x1ec01644b9bbcef2055130a01fa4479b32d78a6b7005714ede86aad3dfe96050, 0x302282feefc69b5efe00672f8e819a14549f2def850356737a66fd80953d7fcc) +f_x_b: [0x28b3edb320840173b7459ebf3ac0b0ae17a0b1ab3e2933dc63c0543cefc0dbd4, 0x29f50d3e3d81b8ef7d3c108d3f915ca9cbd44dcd9fe14d958a953659dba6b728] +q_0_x_b: [0x29f50d3e3d81b8ef7d3c108d3f915ca9cbd44dcd9fe14d958a953659dba6b728, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x1ec01644b9bbcef2055130a01fa4479b32d78a6b7005714ede86aad3dfe96050 0x302282feefc69b5efe00672f8e819a14549f2def850356737a66fd80953d7fcc +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x088cc2c738fd710509a3e942fa3d9e9405b58b33398aea6a009387a58aa71d02, 0x05717bb7ba85afaf1c465089e3a56ce8da898839e381aa719704e97095b05345, 0x1c01a1d13b2b38c56231055a8da499b9eb9f1306d71caa2c88fef22f9914808c, 0x012da239cea90d94d7f1c1f2ba54b728518623fdea7784cbc08ec6c66b04212d, 0x197083e0da56b18dd10de83540be07405fc98d4ddfe7ca5be477beb79d0a5576, 0x17b6a0c54871d0c2ed9b83106b05856f9bb9a5a46af7e37294e5de124cfb0a20, 0x1bcec07e7379b1dcb4597118727d2902e7b6de9e864b8bb5603a24a54d971d86, 0x26602dbb3b62881d15bc342b51f688a311d069e8af33faa89d0171b81c1f6d6e, 0x180f812608586de7231874ef49eb108b867b72188c35f096e033a4d608ea3c37, 0x10665f6baa32723907837a20b1fe6bad9adb0765b80247ffa9057b5c54d3243f, 0x13e40cbc3276600afe69903d0445028d9c94cc56d40b7657674d1a5325adfb3c, 0x07c675bb765b9d3eb0181c84f187d34c78be5441c91542039b72c3af13ea98c5, 0x003d4a61f4704b5081126ed8ce7eb6982adf7c53b3a869b3bb362067f49f6d6f, 0x05a88c264b3741e263ccd2eba329532fe656f9648f902cf44b8f36adc0c00650, 0x0b44a033c5836b300dc7de37ace6f6589fd193031841a75346b95b379b772019, 0x24feebbe276b950a9f17dd6b73a29944eb6e0a8ca07b1ae967d220a3c45c93fe], degree_0: 2, degree_1: 8 } +point: (0x2387996cef8dcaadbdbe95b0dfc2f962b85ee81a140b88ce0003882c8d6e664f, 0x07c495765b41d5c703a603f23469e8c2539457e8e2da404d11273bdd3ed166c6) +f_x_b: [0x2b5b2a31eb4c6e94cb94e8ca5540a178b303746ca343d2f388528a88751e839b, 0x0ae6a09d8bbc72b60370ad0e306b56ea101ff77b7e42923ac06e7a7ad59b9b8c] +q_0_x_b: [0x0ae6a09d8bbc72b60370ad0e306b56ea101ff77b7e42923ac06e7a7ad59b9b8c, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x2387996cef8dcaadbdbe95b0dfc2f962b85ee81a140b88ce0003882c8d6e664f 0x07c495765b41d5c703a603f23469e8c2539457e8e2da404d11273bdd3ed166c6 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x178622bdcfac2ac1b70274667410249f6c95090f6dc7f0f1cc23bf832503a5a1, 0x0c168b7e0630ffb46f845b035a8e91c45f9adde0cb16d0fcbaa2ce580476736b, 0x0fb16e9fe86f1f0cbc5db0ad2837715e3ec8784b74143bb2daeda2ecf8e4ccdc, 0x0f22f3f390015945f70eb842e539586a5312470535eb3d43539bf0e22f92b4eb, 0x017b66057a57dd67f327b122a03506a7c4140e3754f3c3b1fcbbc4584296a7ac, 0x18dbfdbedf3d77211ae7c0a8f18d49bd2eecdbeab23a43c48907a04f1d8db5e6, 0x29e3b3e61f519759464b11045ae762ff7323a1fc2066b462bee7fcc1e235bb00, 0x2ff020461fb45d8129f5a0b3aad4b7c3ca39de762ed421ec9fe83deedcf14a94, 0x23768d455e391198c42d9def71bafec187758fa27769d446ee5d282de3ffa877, 0x09292d4ff8cd19b9cd76440ec0d13cb75fc11d5723ec63a19d2d0e5de174b0ea, 0x29588a6b27d8a8c7574bdfeb0dc4119095cfb4ccaff6357f6ba2189e51048d22, 0x2c4d6db044dca22823521f3a76b29d011feb7003e543b27d45bb4134b3188237, 0x000fb227a29871dc496443997aac1d2263f3766bb8ef61abc8593f47a45e91f7, 0x12e90d5f2e376d94f508b86c9b90406b9af6ccd23f6ad2dff1caf338a4e8a8e7, 0x19535c3329dda1249b81e8afb4a72b4299cf75a2b312914bb09e68ae65bdc708, 0x191d104f896ba357e784c76058fbc25c2f40a54a226d1b3315f573876a8a47bd], degree_0: 2, degree_1: 8 } +point: (0x126c99fe6f9739e915f24b64273d9fe9d6e8f9ae4b9fa94d7c003b64f80c9c78, 0x129bca3110d145fa78a1ca07ab31ae38deee84b96e8a3a31148cf1c090369820) +f_x_b: [0x2b25b8bce3d11a7dea59456489cf240f734f8dd02fb29148542e285abb5c047f, 0x10b1f1452bfd996fc7424dcec3a84a92cb390a7589a66663643679202ba8a235] +q_0_x_b: [0x10b1f1452bfd996fc7424dcec3a84a92cb390a7589a66663643679202ba8a235, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x126c99fe6f9739e915f24b64273d9fe9d6e8f9ae4b9fa94d7c003b64f80c9c78 0x129bca3110d145fa78a1ca07ab31ae38deee84b96e8a3a31148cf1c090369820 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x2797b6752243bcd852a26e3f2ab951ba1a557ed20ec7a47948d263983fa2894d, 0x20f6c9ed83f294fcf80e7dd9922fa64b4d13107f92c2e7b3d0cc83a614eeb143, 0x0665711b67fd014f5c9e7934100c1d83b81689d849255b87635a990b39648188, 0x0df37ddc1ba4aa5ba4b46f061ffa7670cfbf926e16779dccfa1986e15be55f5c, 0x2dd4e9d6aa8c13fe2ce29b74bd8baec0b3c1bb50e9b0b5ac35581a7dfc6d15fa, 0x1bc825916bbe9e5a9b9150abceb6a919337ca7ff96744d596f88459280b1582b, 0x20889f9d9e9bf3e911bf2d33acfd8e49222f867a80ebe4ded7106674feb0a5b1, 0x072f799be18040b272156bee3fdae5325eab7357d27cab466efc3034a37d6985, 0x2d1a103d60345de5d624c01c4bbfb600ca0129b7ac7ca4b4e48802d9b40533e9, 0x0d91a0eaf153078c2d2c053f1bb603070ca969110f4981b8410698039eee4801, 0x08cb23061c36bb93c733545ad02bb42799ef63b581d58ab0d128542d509b875f, 0x1d80fb901fc0a63359920ddb6f8a7e23bec52419c7de64d5326eb5df5bc8b344, 0x25f6e28e3a53848ab4e0eaf9938ae9ac7d25c31725dc1bc0ef9ddb0da3883e02, 0x0b938564d95c0bbf7bbe5ae79b54342716938a91f73450b908c28dfc991c3f12, 0x0fc0bdf29a013f3df99e7fa930013a8e38037c2e657f22b52f62e08f85213118, 0x0ef974a4cc43b8bd3f36f8325dc467f8a2ffaba96a0ff7afe647f6fd079f1519], degree_0: 2, degree_1: 8 } +point: (0x03e6bfee76c11dc1dc75f414008d2590ce5519b65d1f52851af5add70be58ab2, 0x05eae05ce1ebc06a036d7f0b720a437b89b01624752305c3f96d6d9d7abd50f1) +f_x_b: [0x270569fb60db3de0e68aab5f8c1ff19536d85c5042fe88afdb81907b9c2645cd, 0x056fcb31036c05b079e788de7cf87efab57894502084b7de5ecea3034202b0c7] +q_0_x_b: [0x056fcb31036c05b079e788de7cf87efab57894502084b7de5ecea3034202b0c7, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x03e6bfee76c11dc1dc75f414008d2590ce5519b65d1f52851af5add70be58ab2 0x05eae05ce1ebc06a036d7f0b720a437b89b01624752305c3f96d6d9d7abd50f1 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x104cc03d410e205b3efad8fa02076b4ab102b28320e7df92490fb77bc534f683, 0x20fc315086b230d4070ccea9f54350b93af438ca8c11dfd220ad9f5bebf3643b, 0x09faa8c2f3a60e9621fef56327e8b6a85efd33172f8484b011bf661222f2c0ab, 0x232015624077597123a11b9bbd5c626dd9e05532496b433b7f2715f5b124a24f, 0x27fe6195f0202f0e988579de9d35e4c628deda71822a0b7601b3c9b2aa8e4fd6, 0x28ea595b3c68fbb88d99a084a8dc5f495f36d94d62a7360b6d05784f9cd4e61a, 0x00620b72c083f7b5cb4d348d1532082ed93b98ebcd3f424d9dd666e9d991a847, 0x21f213e7dcb5be19381f4a7e0a7c3392322e0112220c82d648603c7d62854643, 0x1f9e9af8c5df97951a28396f862b9a2e0fc476774470a08cc57f899b4fb96e4a, 0x1e9bba373e3bb18e2968fa1e7f6e30d2bc84b73e0b8767c48e2beb920e007885, 0x1a5ba0e9c0292c75f19a13eaa4f30f64963d985eee335cb97b145af25e27a951, 0x0500a3f3af2f8aff7dfa03a839c168e9522a95d062da9502386df73d48f03c95, 0x0b6557387af4495e17016b63a4cc272e56591add7f6274fddeb1463ccf50618a, 0x06617ddc3fde8e2eb072b296abf73a9658a4edbf7ad573fe1dead18e0fecdd80, 0x2a84069b8c302cc45558d02086dd8b157f096ffc2c3be7eea7a83351536536f3, 0x07ba9e79ce4f09bbc38a5bc9c81e6f7ac81927878e41825aa03a0232fe688637], degree_0: 2, degree_1: 8 } +point: (0x02e87b2a7477a3dfe9e43a97c3803e3ab98e0828875ceb4337abaf43c5707fe6, 0x2640faf037b931a2c29dffa7fbc15c9a764b62dacbabb10904d229b80e797ab0) +f_x_b: [0x1d32e4c3bc1d8370cad34e73082928c66fc97608c21fb5aa06a7a87ac794635d, 0x165cebbcc2825777d82cce88cfcc0ace9160415d60d4f5653788ca58a0ec3b14] +q_0_x_b: [0x165cebbcc2825777d82cce88cfcc0ace9160415d60d4f5653788ca58a0ec3b14, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x02e87b2a7477a3dfe9e43a97c3803e3ab98e0828875ceb4337abaf43c5707fe6 0x2640faf037b931a2c29dffa7fbc15c9a764b62dacbabb10904d229b80e797ab0 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x277092dd21407b24088a0f71afcfa3ae97f4bbfc196575c321876ed7afbfcf8b, 0x01fdbfddc7724b39dafb53d5616e6e6570af89051c9467afb6ce2dcc683e20fb, 0x0679dd03450e449c675b4ed6cf2cfbe8a240a02c4912343f8145609757004544, 0x2d5463bf2053a16e2b228b9cbd7731754a2213a0a79927bd8eb3d592e75916ec, 0x19ce09a20644cd719f0f7097e87fae7b089a4ef0bfaf015d4281cb7bf376b5f7, 0x0b36fc3e6335ef870924cc8116a349f36a36b4c0dab4565e14559acb1a5e555a, 0x2c53987e7a8147b7bd17ce8c0c26015ca9eebc559e93f8002c16999cf987a3c8, 0x060203761fef2838f2dcb99487af27b1377f5edf18888a0f7e6bba57ddaeb590, 0x1638774fce85cdd5c857a59081fffc2dfb65156111558c5d5802044f7d8d2e46, 0x26de30107e8e5ad9ed73aa589394559e321c72df1adabd2dcf7fab169e8b1eda, 0x05a6b47cd0a2cebd118bebfa6622ec15fc1514a052fae2d497dd998767fad565, 0x2eaeb72f4962ba66062a317b53a4b579423214041b2c73db9696b3866a2c8eae, 0x034f41db3ff78d1b302d84bfe462b3c419c52e55bfbcce0284f9e24a7f03d71a, 0x26a65da9f1cfc59414d56bd0f0bfb89d02bf4973e35e48767b16390411b0bb05, 0x15491db551169deb7a6a94200d627bffb07a29bdf8be7b45b480038be4578723, 0x19d05a1c6b9ce55b16ab990160438705471261bd2a75a15822ca38a7c15d51e3], degree_0: 2, degree_1: 8 } +point: (0x16ccb2481b82213a69d346c1620ece644c2d1b4ff9498c07327ed57da9e6df82, 0x22866fc7d2426f4a33c1a4f9cae665fc84bc76ca462a2971ffd9844597b1b951) +f_x_b: [0x2a2dec881f83252c8349ff66d2edf1b588be80405814f958994f96668d290724, 0x1f0c076c36e77ebabbd3975263dc9c3f5469589f94ba69bbda7a2ae129636fb2] +q_0_x_b: [0x1f0c076c36e77ebabbd3975263dc9c3f5469589f94ba69bbda7a2ae129636fb2, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x16ccb2481b82213a69d346c1620ece644c2d1b4ff9498c07327ed57da9e6df82 0x22866fc7d2426f4a33c1a4f9cae665fc84bc76ca462a2971ffd9844597b1b951 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x0f8b13634581a3f0a4fd366a81cb8437a011f97015dcaeed7633af77446702b6, 0x17c362271d52cc4522f0d15344ff8adfc1cc1d9f9cca02da4f77826bdef77b85, 0x0d53326246744353ce43ea7e4843afe9939fc4e7d4c9f7420616f341ef87aef6, 0x21b8e001e2cf87e373fd5c889edfbca67327696f69b7f3f6bbb1edbeade5f572, 0x290293fb7461a667803c035025965bdc79a499ad155cdbf4481aeb3d044fd7fd, 0x0832cc4f94d2e06fae044d31635ca404ac4d3ffc5ea2e301df8a7c90d64fa40b, 0x257c648132d3d9ee5ed1add9b95dda5ef104be7d8d35b12eb70d57ce6325e064, 0x125b1935ed11e4f6ca22d18d327751c9317c5f7a1b2ff32c8a034ec1b7c03cc3, 0x11aa8bf718ce7c96953a33fa827369f902c1b62695f162f97d71e57266242e18, 0x21e4743e1e3f4b833de505e57688a598062774bca65bdcbf4fd86c206a3cddcf, 0x02749526e1c5abd50762756a07f076e73b16793a9effce94c30d4e66bc8114e9, 0x06cb062f389422a549cf8ee326fe2106786ba3bdf8391b0b78af12234283eb6a, 0x2bb08d9d902e1ff2db941861ff205762688fd84f94c47fcd0131c7d123f8b310, 0x23c1b59bfb2855df94ed55aea082ea6ea22d6466658a350655e1947dcba60e94, 0x088a81ab2a7b5bf8bee3d70b910b11ce553043e4899018abd943c7bb90eb32d9, 0x1dbd803e16ade422a902ae3904416fe27406caca70fe86beeb0ac66332d33a8b], degree_0: 2, degree_1: 8 } +point: (0x137f2aba275cc034d8f23e1d50e8cd27f694fd0f996c2b84b67663ed5da68be9, 0x2d0fc92a7b06c46f126d0a03a13a760c8bc2f27602e5734c5923fcc36f0cd8f6) +f_x_b: [0x24766d75fdac7321a84aa118f453f65bf94433d3dd1ca49626459a9f36492b38, 0x091bc023ae26ded9cba47a3408c09c2a7e19c6e8d2a19cd950881119d84d7f4a] +q_0_x_b: [0x091bc023ae26ded9cba47a3408c09c2a7e19c6e8d2a19cd950881119d84d7f4a, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x137f2aba275cc034d8f23e1d50e8cd27f694fd0f996c2b84b67663ed5da68be9 0x2d0fc92a7b06c46f126d0a03a13a760c8bc2f27602e5734c5923fcc36f0cd8f6 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x09bf9497ada87876a8b185e9fe3eff574b2bc4e86deb4d5b63d05b3f2c116471, 0x23acab3bebcb1574a5783791e026264a4955d798c8133eda9b0d6df5d2f9b492, 0x27bd9c719a5a5a005e940b40cfc3ca2e3c1f8dd7269d1cdc5c46141585e90880, 0x0fa3855af6e71f81e482dc94bbed91dbbd42040633531a35d815a83a5fbc1482, 0x2e5e511f508358526e0cfa4ab2bec58505d07fe8b4cbff84965b58be046aca7a, 0x150b30e62887595fff78e50d7e6c44f5f6ac64b4495ed7d7edf37eb42cb7ca62, 0x1f20a556b17cc3046c7b43b2fded1f78a6fe1147d8544b105e85aef6094b1b87, 0x1a65c86b5850e75594eaee5a8a9f828c3c1815ee88d91c1e6232a1350dcb355b, 0x20b859b24eb956f4e92e006b02d209d527467e652e913af78be2a539ed4afbba, 0x303c115941301c2eb3ea1a5d022d1906d830d17bd02d59cb9c05d6b3b304c6bb, 0x18f1c433bece68b5932dde86a551994834a59710986ae90a4cc17b11b2724f09, 0x0e8cc22d4cae37bc62afb16526533dcf2deb306ae5a52fbd1eeef9bfd84767a5, 0x28b69da0d96e5c343ebeffe163e9e09f650f4d17fd2b458eb40ae84e4a3440cb, 0x0bc2c3f897215db354907dfdde931b30146bae41539f3a39b8788361ebe8a9d8, 0x1b73a5c5cccd4f86eeea821279becf0d872b12e00d3570ef5ce47129c64b15ac, 0x1222f92e6bbbf4104fda13ac6f90934c694fea761ad933b5aca2dc4532a32e9f], degree_0: 2, degree_1: 8 } +point: (0x11d5a897309a439ca0fb9bbecd977302870542962f3ebe370e370845cb2ed6e6, 0x21836fd5bbf02f1ceb168b8b1eead1b2defff6ae6125f383066f279d9c086c6d) +f_x_b: [0x19fc83c93663decb7e5f6e823d80a1ac1fb151cf1a634e1b546a42550f61a6c2, 0x142b96895d093d45c4fa24c06e704061969a372b850cf07720eea103dc75c025] +q_0_x_b: [0x142b96895d093d45c4fa24c06e704061969a372b850cf07720eea103dc75c025, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x11d5a897309a439ca0fb9bbecd977302870542962f3ebe370e370845cb2ed6e6 0x21836fd5bbf02f1ceb168b8b1eead1b2defff6ae6125f383066f279d9c086c6d +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x1c3ac34e6e356df8d86fefd82c242bb8e1fdff7cca033da959efa395fec39c75, 0x18a4f6fd166076e474cdf28f0177dceaef65e081c28d55d3dd0a235d6d02df34, 0x03f209df2a96005111af53a63570c35217b9a8e059b1275506fc29efe0c1b287, 0x2c0f3d96fcc68b512ce64745756f7af37f3a3983dafdef91ddd24b749408af49, 0x2dbf898f0b2b758464f0f6cf1484e3aeb5d098b0af8403ad96e9c3204cfdc5ed, 0x1731cc61a5b877f4ea2679acb44b0371e673e07556283151eea56ce15c76d39c, 0x0b51b67ec633db0a66d42e3ec8fd18040887e5a1cdd903978841d4d448dcdbc8, 0x1a5a379470047573ba8a70ed7a65adccd87572dea876fcf3f28d2d6f3ba39c38, 0x00794b9ca415f758778541986b7f9c5199b50b108e52f3263f2a1348038da9ed, 0x2ff3c93c77a9fa53a6e4277d22743e54bb5206360e34d52948066fca6f8f5c26, 0x09fd80c0ba3e9666abcb7cd6e88bd20864fb55b7634c3fb5e50ed610c6327bc9, 0x10477aeade0ce8e6d9d5a2874bf75557eefa64727469ff20f84caa42b4136270, 0x068a6753c4ede3bdb9ede548ef62e1470d919afa3f1a1fc2973fe787a721e723, 0x29ba14e3599e0c5698874c72512431b363245df362df0b48bd3cca16a266c3f1, 0x2e0b5e4954fdcc1c27cba2bbde9da0c2b4581f9bd7812174f2c400d9dcc1edc3, 0x2b866cb266a04bb5ff16d2393123e4a7631c07c0cd6416f23db77fa2e6614ec6], degree_0: 2, degree_1: 8 } +point: (0x135510f3ac671467d0e0db1ef1917050aa419c9bc9e38c82e6e0150fe0fbfad3, 0x0164337fd23315ad2f606a12785066e209a0821d3357c05f9320a948822fecdd) +f_x_b: [0x1c0c3da5f0d8a10819224fd69c09e7018418e29cf63f79d4ae371fc0474d513b, 0x10a6fe7ea781e25daa6492573a878b23f1bebf90b2d6a27555b94db8c2da2fdc] +q_0_x_b: [0x10a6fe7ea781e25daa6492573a878b23f1bebf90b2d6a27555b94db8c2da2fdc, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x135510f3ac671467d0e0db1ef1917050aa419c9bc9e38c82e6e0150fe0fbfad3 0x0164337fd23315ad2f606a12785066e209a0821d3357c05f9320a948822fecdd +here2 +res: true +m: 16, n: 2 +omega 0: 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000 +omega 1: 0x21082ca216cbbf4e1c6e4f4594dd508c996dfbe1174efb98b11509c6e306460b +n: 2 +m: 16 +start to compute the scalars +f_x_b_scalars: [0x00000000000000000000000000000000000000000000000000000f1cd282bec0, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1eb80b8fe2b81] +lagrange scalars: [0x000000000000000000000000000000000000000000000000000000f1cd282bec, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f4f2bc8fe2b9, 0x0dd6169411fd6da4eaea98009b6353a6b09778009a9ed7b9419364e17692b261, 0x06e80b18e9bcec4aa0d3b1e718e8e5afed01a817c17e95b4eae90e9b00f38915, 0x15abf3a69855b2340a466d7350f927ac5f7a68b22144a4aeeebb83c92b4ec797, 0x11d03c8830929ea3c95be582205acb2085d0ffb9904ddd418e19a131d876259c, 0x03981d79ecbf8409d58b02ae3bf01e43353a73a0ff779bbe6518fe0873ab6be2, 0x0dbc067fad3b880759be1573588b0947949500577e43685c288ffdd6583862bf, 0x30644de43fc26b3ac6b37528a757f1e691631412ee3a46cbabeef2b4fbf5ac89, 0x0000005f164a2349f6688b093c1b99a4648b3823b254c683baa201e9f806e250, 0x2b66983d871c2ccf5bebc18c2d60c1e668521d455e8aa2123a554031969472aa, 0x0353cece3c0e4ce6e84302c6e2c0644f2a968757677489aa065dce4190f25e3a, 0x185d0245c482f69090498acb383720f48f10382754f1df5d7e873baf7f193e6c, 0x20264cef08da511ead7493d9b15c97ba1e29182e411830fd9a32787445ef2bb9, 0x0d819c7c88243fb902912ee7079f3a5657f4f308ea52bb7136242be6458cfb92, 0x07205c7df04db592910f4d4d7b6ba13ad2c356123706a88f9d333497cc4cad9f, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f4de9621df10, 0x00000000000000000000000000000000000000000000000000000078e69415f6, 0x16c6d525b08eb71edd59d69629bef4bd7c7c519cfd7a2dbd49fc5b3ca05ea33c, 0x213515af1627d0bfcf69b6a7bb020a897fe107352612a76867e4636b85163dd9, 0x1ab85aa2b7f98cae8dc81bcdf78ff2db6302137d5cc78813c0d93b0e2a32818a, 0x1e941206668b426004758882872161203b87db4a3bdf15d96dfbce352933a9a5, 0x1198eb78f349233ea5f3e902a8320f01f6cc7e6158ccfbc136f5fe131747372f, 0x148797514945a89cb6e83dcd3b8a30e77644f144c09da3355df2a500907b308c, 0x0000008ea16f34eef19cd08dda29667696d0d4358b7f29c597f302a4ebc33eb0, 0x30644e13cae77cdfc1e7baad4565beb8c3a8b024c764aa0d893ff3d0a82880e1, 0x10c518ecc63a42bcf4639ffb3bc9c243f5ee65d6bd0a2d91511c488085971cfb, 0x04f35eddc6e9b38fefd85740034f469c69725ede55370724e08dcc30f6f09759, 0x18074c56ad910ae0484877608242753dfedb1c3a2074d50259a7f09ea0e67465, 0x103e0168226b0e30f55a898eaa29ecbf70e5dd5ee62dbd09f17c034e34bbb268, 0x0db1a9052b85652b924ce66d6a75d4ed694b871476e729a8e2716fe9cbdf89fe, 0x07005422d8b79c9b8692284939873a2b71def35fd94e5f152a5507401d6af957] +start to compute the affine bases +start to compute the lagrange bases +lagrange scalars: [0x000000000000000000000000000000000000000000000000000000f1cd282bec, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f4f2bc8fe2b9, 0x0dd6169411fd6da4eaea98009b6353a6b09778009a9ed7b9419364e17692b261, 0x06e80b18e9bcec4aa0d3b1e718e8e5afed01a817c17e95b4eae90e9b00f38915, 0x15abf3a69855b2340a466d7350f927ac5f7a68b22144a4aeeebb83c92b4ec797, 0x11d03c8830929ea3c95be582205acb2085d0ffb9904ddd418e19a131d876259c, 0x03981d79ecbf8409d58b02ae3bf01e43353a73a0ff779bbe6518fe0873ab6be2, 0x0dbc067fad3b880759be1573588b0947949500577e43685c288ffdd6583862bf, 0x30644de43fc26b3ac6b37528a757f1e691631412ee3a46cbabeef2b4fbf5ac89, 0x0000005f164a2349f6688b093c1b99a4648b3823b254c683baa201e9f806e250, 0x2b66983d871c2ccf5bebc18c2d60c1e668521d455e8aa2123a554031969472aa, 0x0353cece3c0e4ce6e84302c6e2c0644f2a968757677489aa065dce4190f25e3a, 0x185d0245c482f69090498acb383720f48f10382754f1df5d7e873baf7f193e6c, 0x20264cef08da511ead7493d9b15c97ba1e29182e411830fd9a32787445ef2bb9, 0x0d819c7c88243fb902912ee7079f3a5657f4f308ea52bb7136242be6458cfb92, 0x07205c7df04db592910f4d4d7b6ba13ad2c356123706a88f9d333497cc4cad9f, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f4de9621df10, 0x00000000000000000000000000000000000000000000000000000078e69415f6, 0x16c6d525b08eb71edd59d69629bef4bd7c7c519cfd7a2dbd49fc5b3ca05ea33c, 0x213515af1627d0bfcf69b6a7bb020a897fe107352612a76867e4636b85163dd9, 0x1ab85aa2b7f98cae8dc81bcdf78ff2db6302137d5cc78813c0d93b0e2a32818a, 0x1e941206668b426004758882872161203b87db4a3bdf15d96dfbce352933a9a5, 0x1198eb78f349233ea5f3e902a8320f01f6cc7e6158ccfbc136f5fe131747372f, 0x148797514945a89cb6e83dcd3b8a30e77644f144c09da3355df2a500907b308c, 0x0000008ea16f34eef19cd08dda29667696d0d4358b7f29c597f302a4ebc33eb0, 0x30644e13cae77cdfc1e7baad4565beb8c3a8b024c764aa0d893ff3d0a82880e1, 0x10c518ecc63a42bcf4639ffb3bc9c243f5ee65d6bd0a2d91511c488085971cfb, 0x04f35eddc6e9b38fefd85740034f469c69725ede55370724e08dcc30f6f09759, 0x18074c56ad910ae0484877608242753dfedb1c3a2074d50259a7f09ea0e67465, 0x103e0168226b0e30f55a898eaa29ecbf70e5dd5ee62dbd09f17c034e34bbb268, 0x0db1a9052b85652b924ce66d6a75d4ed694b871476e729a8e2716fe9cbdf89fe, 0x07005422d8b79c9b8692284939873a2b71def35fd94e5f152a5507401d6af957] +finished commit +poly: BivariatePolynomial { coefficients: [0x2f8fff6d59c70b0bfbbfb9dbcc996f02d19a1cd349c5498ed15a07ba866cc7a5, 0x0ff73c7a989ce2b73a85ba7b6df61b18df2bb80cc316664fd110322885255f8a, 0x181c1a3488c645394f340ade7c0c65c9d3f5972057f1c394b66b54c8fd32efe4, 0x29ffb80d093ad0080cba341a8735ffd941ee85b1075e1aae697de12eff2c44f4, 0x15168bdb338a09f7909ad0bfd28b05aaec5da61b41cad9c13408307f9b75591a, 0x2ab2b6d18ffdc8a48d84876debbb4dee032156de05474d772b739e6dd0fc7537, 0x0e5cefbac28373be56857646d1bd0bffd4913b341cce2cc019ad31548d35b884, 0x1c516b4265715605ed81f0c5f9eeb57ef04a72d8e76ba424c0acd508b0b03e3e, 0x224b5e4fc7a8a75446b5d4665f9a2df004227921041130adf4b184eecb927d57, 0x15ecbd52b5d40b74c8a757cfeb93374699a09de7d1bb1f6ca941c7fe4e2007b3, 0x24c4ffb301f5c7d16adf08084e4bc893ee3cb8a363c98f482f31f355738d868c, 0x0ada4a52c423369b746a6eecceadae56e6fedde075df8e33c12219c69b2670dd, 0x20b0752074181e695a40a23a8b1ee0652e9d206ffc78ddcd86de678200ed6027, 0x1b029c29960d7d91347d51ad93b2494a8725fc87f78836cb60fc65b99463c401, 0x23abb0e65b460f8a1c941880b2f09ac8e04f23d90ba08080b8334f6d59cd0459, 0x00de4a9f939cc0b90d45ca867383f7e6d0632ad9bf0f9efa2f8059550ef3c4a4, 0x1ec24f80bacd9f3cc016e65f76abbeb53da61c88f66f5ab3bcdd38c22445415d, 0x2c49e76160448a1b9f2d0a34e280fafae94180ecbcf4e7be5e3afe97ba8c243e, 0x2d4cf48f69df660a011574074ad1f4de1b83527a9f7a2c0da80f1790cb30a48e, 0x2e915ae67ffb792eb33ab85cb498fb439a995c6750af1aba7f2d539f19777fb7, 0x0bc01c16b9ffbeede4890cbbe2d882e26cb9f4446c06d3c59cc81d5690f867ce, 0x160125cde189224184fd4642698b26b9892aaa730b7e74e16372eeed52cc3091, 0x0c8ce0204469fc4e9de0a8c4545a2b79224c98710bf35eb3a0937b67bab08e86, 0x2a89d660bd1a7d29a82c8ab08d7df7a68d04aaf1349b38869a0e658ed639aeda, 0x29070f526134ae57538ebd5977213ed56a5e91f7501737a5f5728440dce39a6f, 0x0decbe52ab128987b439e2618a1ed617881e21ef3627b630e4eefb4e27b8d892, 0x2c95cb20ce65dd0c2a887a41b072a73553db0815d291638d37bf22685a2a5ad9, 0x0a9710953dd682fa1d232054a396da77c437ec2e147593038d304334d1bf3cb9, 0x0ce1bec9069a36e8155d08e3009db1a89d50a65e6d66bd8e5333fedefab33ad1, 0x063dfcde59b49a54adb04d3f11fa5d7e3d7384debf1fc184c250115b1b683862, 0x0f9c9585a5c31adcfcaca8723217e1d0a735f0c3ea16ee19380e35e3b65962be, 0x0b827bd61259f8b6b05275af9f72912591375210ca7758d52cc97eb646259fb3], degree_0: 2, degree_1: 16 } +point: (0x12d2a857f7cf96964664bfa2ec9002170c770a638e55a1bc5ab4c4fbfd998b14, 0x01a690a47d2b2c084426f4c862e6f87f83de4f09db29ed650e298de52732eddd) +f_x_b: [0x257d83db820a72d2f756ccff56f530db0419b5eb0961c24ea64150abede80b3b, 0x0042ed2030fb1ce92d68e7dadf5b5dede823d64955d85bab8c46dfea0b5138e8] +q_0_x_b: [0x0042ed2030fb1ce92d68e7dadf5b5dede823d64955d85bab8c46dfea0b5138e8, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x12d2a857f7cf96964664bfa2ec9002170c770a638e55a1bc5ab4c4fbfd998b14 0x01a690a47d2b2c084426f4c862e6f87f83de4f09db29ed650e298de52732eddd +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x23ea8ded791ab1fb7772da9c34a381716793316a367f5d438f05322d5a0ff55b, 0x0e5c05610a83917d4ad0deb6aa919b4ad028423004567b5877da1b4cb0d7cc77, 0x13edb4d06737f7fa4ec30c3ad13c2695cf3a38498317051ee54ca21ab3c45baf, 0x2b66fd74310a6bd4c525dba9fcd78703c6be50301e8aa9ce57ce17a201806952, 0x1a92353bcce4211375d744347ecd7140e56cede94c917f1787748bbeb462407a, 0x0e70e5280ceaa029db172424887b29ddb1a599faad2808ec2ed1741a8c7a0301, 0x205bfe113f451d4215fc3bb9721e81c14f0b25a4dafb43aeccd15fd287c5c9b9, 0x08f1a456313718ba9b2c931c00422d89f7d6f26547d65904df99ff1872d16b19, 0x0e1f23f73b2d2761c70872b8df67ce6f8a680fc0f8c00f175e488483c61b5ac3, 0x2ae0f0df84c5337a1607fbf784ac01f3b0091bd4d7e2aacf65a809d6e83ef76c, 0x1048d6f6626cc5f8d99843bc3a0b8e5b5f95f3a43d25d841ca1f7934a779dacb, 0x221c41536e77d3cd757f0304f12ec2eed3a506f72c804a5fcb39f61cf2ad747a, 0x2de958098021c72e7dc25bb46907e9ef40eada30209e768e1485742bb5c103a7, 0x2f92c6fc7a4c52c3d6652f779c0b8d51fa0b5135d09c472081cb1ecade0bafcf, 0x0a2973696c9f24644de1551777e8f11d9d9be05ee466522fe1a52ed68186a8ca, 0x11154e7b09820cfdc9c7286f0bd8d9c178a76983157da84984aec9f0ae1018da, 0x079d7d90bd4739bca138dcd6f15a28ad8ae236664128400ae97de072eb5b8bf4, 0x29eb10c5becd6f41198c57b9fd69ce4c53ae3c8794904224927e8f2ca25cfdbc, 0x2e15c14395b306ca689d928915761666bf9d79cece08c5b2b383287dc1568412, 0x0ba181c48b08961ceff1857f030c7b36f49741e218f9797960e8836f544c413a, 0x2deb377f6795e9d56b8086205bf262d4d12c86b446a5e144086777b32326f491, 0x1491ab4f05a5a5d8802bae711c2407e52096a9ede07b703d505b112bc6ee1ec2, 0x21a101f858fd4408b82d5917c3c4377649102644a3bb1c5e4a6ae108bfb6c60f, 0x118083b6c8fb7a841c2277e80d9f477aa92580e37b45a17ab24b413bb5eb9ad8, 0x0b6f8405e57a4ef56caabdd8446117dc744816352f0c6329c284f08a96c92c9f, 0x2a247edd6b6562855897d0e313792bf5461a026de18e2f2dd2cd8ec1fbe0a707, 0x195b5487efbc654c0493e1c87da1eea402ef7a5feda27072766958ff3344c891, 0x0a33049ed7af4545684a3e363e89fe014219d5b23ef94ee92905aa25a7bb556f, 0x017784d9d1632414428d21a5e4bcb27346ebf48042d4c7c74a764760bc0cd8e5, 0x0406cd959dbdfc84465d4c01f59998e3a56b13f3ac57eb05f8b61a66a8edb213, 0x1304635dbfa302ba80ca831c5a2215b1a86f496f178119de1c50f2bbc07174f4, 0x251c973f3d063f2623ae973b7f01d6c903e4204d4c1aafde77ae507c06bc3f71], degree_0: 2, degree_1: 16 } +point: (0x0243f7911020086fe38f0a237ed025cf1e0ded876810d1bca1ffae066da7ac1c, 0x0c51455c53b6376600b59c93d7215ea690400c73489b35ba2d5b240a34648161) +f_x_b: [0x162135c807aaaa4625126c3c6a253494585a45eb62cec32f10fecbec4fa1bace, 0x2328ee45ab553fc05d3a10bef217bd74f8af4fd863056ab8ed673f201f57a1db] +q_0_x_b: [0x2328ee45ab553fc05d3a10bef217bd74f8af4fd863056ab8ed673f201f57a1db, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x0243f7911020086fe38f0a237ed025cf1e0ded876810d1bca1ffae066da7ac1c 0x0c51455c53b6376600b59c93d7215ea690400c73489b35ba2d5b240a34648161 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x00a40e3edc4b5b58aabdcd9b0133baa7434e13b2c673313fa839b820dc28f7cb, 0x075742e2f8fbff4811c1af15f1244dd61c2adeeb81687b8e9ef7d77ffb4faf70, 0x1fae6c73fa354031429759b010d064d217774e828bc7353eca545b22ba03aef4, 0x29665b858bee95b619d1678214b727b952af07a59af99716c1b61e3d623b339c, 0x0838a758c6da110fe12b696f78e64cb4d33e7b6f63e6882167d11c8647dbf422, 0x2475a0f6056030e36140cdb63376e74368c6662f2d94665db522fa89eb180c1f, 0x26f559516bee997e1eefd0837915f37ed9dc585cbe9244bce02b153c999bb8fc, 0x2c2a9f13ac9fb814d4ba60a2a16c9a8d318a969208dca6ac84c9b697f2a87cc9, 0x2feba57cb2099376f5e0a5c30b8651b6c29659960d804dc966edb617015a5d1f, 0x1e30407704b66518d96e92ecf7e298628a33652c89842718cbd45a70a8915f9e, 0x25841959f004ad6718938b0be9db7fb2a62ff813a52183eb39ab3b144eb3c174, 0x16aaf07e1f55419710cffa4ad1fd2bfc192b4c39a950f00003aa4164ced26851, 0x21b6d06608250746f4bd41caeeda22012f9aa047486971a9207f075cd42bd8aa, 0x00faeab88915c4fa2be6ab63a1e7d24ec8b3e5cf4f4ffd8b0f0a44bfa8e19ff1, 0x29e84fd058926fce0150ede6ba1e9cb72f636c9cd68ced72ef94018f968284e8, 0x0aaa342e45c92bf8e184db670da60afe2c6d64515ce0db48151c3fbddb526080, 0x22e647b6f32d6296418fab7b22fe8a5b34d5c5e88310204d3124ccf376f5118e, 0x05b3c8bc1781bf81a53c548a779f77cec5b5bf03d3621dbdb20135b99500d7a7, 0x063adb83da57a355c833e4f806c439e1a55e18b475233b39eb6455181273d713, 0x209afe06f3bbf7afc6fcc81f04c2f754f913ff6cd35d235584081664e56a41ec, 0x1ebe932f0715bc8b8b9c99cbfac3b06d9c654b268be3bb86bc55d72e23a2fbf6, 0x1eaefd7e53c9207bf81fff30729ee6d851c611a2215ffd9cc4ff0c1cc8ba093d, 0x2a54b3bcaacb4e70e4a86ecc106f486f2e54b89d37babb3bc93829ab32ad42ae, 0x2b759d20c73dd7f1aa4d495e1f495179712e04128a6bf834e21831cf939457cb, 0x08dc217216d624f0e0881883351cc2bdee7c6c9f450eec751cca9e59ddd8e254, 0x26802b71f2dc6949703ceebb3c9df6e4c8224e61bcaad8da6ab64b2d67c565b7, 0x147dbc4cfcf2003042c8baa756b4ab8218f7f55a80cbf7951a5237fa72615df6, 0x291a9f90b03dcff04e033703e32e80210858eb1e7703ba1e972935c374d1d18f, 0x18c18a611cf65c133d430b054b34793a732e358b4b3b3defd13fc7e1cd29e6ec, 0x305bb843d2395b5d452bc65f30ba62afa763fe1e67cb6fe4fcb7610327055a0a, 0x25dc37148b76b2650eec881a557989a0c1a51f0a1973a3df48784e85128c2270, 0x18dc3e4fa11737f3c8ce6b1ba2fceb7c68699d95b420f3febfd48c38eb36781d], degree_0: 2, degree_1: 16 } +point: (0x2007439461749371bb81907e508679aa89cad632956e10282a3833d7881e5ac1, 0x17f1c52e00b4bc6d7793f7456a31c85d728539dbfb2ab26f0aefd1de6fa383f0) +f_x_b: [0x189751bd92a1dd23e308c0c75dfd12fc88734b928c8aaa77887ee00b29977634, 0x2dc5a6777abfd7b1f36a70f70c2b3afdb6c45a8c9e0ee90c0f9773947c76b72a] +q_0_x_b: [0x2dc5a6777abfd7b1f36a70f70c2b3afdb6c45a8c9e0ee90c0f9773947c76b72a, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x2007439461749371bb81907e508679aa89cad632956e10282a3833d7881e5ac1 0x17f1c52e00b4bc6d7793f7456a31c85d728539dbfb2ab26f0aefd1de6fa383f0 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x263f58285d2b80bfd053eb1d9de5bee3a14b5441583ddcab104df4968c3c79dc, 0x2469ed6bd585d46e1f176cb3284f70e8ab6ccbb7da48d0624e63b92f52a00d49, 0x1c7242d5bdd893a244fc8242564d7cba9a3f3c50ba23351280267f231008ed73, 0x045dff26cabb86aeb6d6fd1b5ed8d7728a050ebb32057bf9bee015b5cc576b42, 0x17024bb2c2623e5ed9b9404b522591ccd1d2505e499224ab53deedcd5bfdba1e, 0x24b35b4e8bb0c24ad9134214b66fe644a9bb7edf8eb722ffabcd558cc21ea0df, 0x115f55aaa87ebc5a02fdc5a8d93ee5e424b63d93e942e9e4f947069804018322, 0x2ce97ace1894fd8abfbbcf832274770dbc210e42b0ea4ccd46a126aed97a3d90, 0x191268fa5edd6f0baa8b3834b5f94ff267b198ad9776e8d8939775a132b0f9a9, 0x2eee4a2ddec57b4001e5a4c066c5a2fabf3caede9e19f9ff328c557c91e03ed7, 0x28b3548d8c00077bf7dd5236315976f38f55923acb951166606fa3685a5814a1, 0x2d20a6879238ae14041b1dd80248199d245b38e77075dcf7a28da054e94efb01, 0x0ce054dbea0be6176fdcab81e4d02bb4f1c7bcf25588605aef24cab94a655f9f, 0x2dd7c00ff5b5abd429de36a6bead5f15367e2d0280d29857f352edfb5376852b, 0x225c4079e18a91469a63911fd8dd7ac8fff43579bf49de23501c43853ba84bab, 0x0696d52c794f5bff7b016dbd0ead267d389d39b139cdbdf385693b82b34f89e3, 0x11b71805720e956f3b27796ca4fc2762484903353515f277aaa7b4a8754dc6ec, 0x00ec418895cd08632982c73a7fd027704211c9395e8416a8a86f25ac4f207aac, 0x2df725b04101fc8dbc5125f26e613b684e11608ec0756d25c5fbdf8b14b957df, 0x1080ef68b157023271585a4833202a673a6a924dcee8710841fdb8c72c2df395, 0x1a1fc0ccbc99d68329143bdf973f6025010a587aa7b50ace7f7831d675d3ce20, 0x077198ca11d52b9d994b05df94f509554260224e70f2c834cd7944f9a6d22ecb, 0x23f9f4e366888f09e64868c4335a865ee9c8ba3e117cdd9fe8cde7b34fe6bc19, 0x1f3a04e7338dd5df13f6e2e909983497c5bc70a03c0e3bcc26948be41453fd3e, 0x09b1df9220c8cdaac1df01f7c52802dd05d2add8ca3c623e8d5f12e9d7b5b91b, 0x032d1ba32c6b0aa3126b44e8ba0db2bc1c22501af23ba811e36e7e1bc10d9d57, 0x02c5ea0709e1082cd5b0200644fd56d76152216ac474ea2e3a8001ec81ffee16, 0x2c695ba9b6e5efa1cb9d8acf27b14bdc7a13168f4111955bdf5d27619013fd2d, 0x020766253724235bc58c3d0b53a34f227a86b57e6a3f37c5047c93d2aebd46a9, 0x22d6011e68d2c0d573e4de0a3835f013fdc76de279e63ee2235097f50e1190bf, 0x0a8b5f237a72338aaac12169382844abd75b87c18b9fc359a95d8eb75aa379bd, 0x21abfd935f034e9cf66e94e2a02cdebf78f3bea53de0fdc9d1b191e89a2ca38a], degree_0: 2, degree_1: 16 } +point: (0x097bb197473ac1cf61ebd9c570d5d19e239d22fb68f2d98c5aefc40b664dd612, 0x053863e217745ee5315de73b00804817637e55fbbaa39f028a9e847e7a2cff93) +f_x_b: [0x008cf4ce0f4ac05d33383be937ada6461c627b24fffad925da930e2233781a58, 0x0c4a20b16ab4ea905b4a89dfec08306108d5f78f5e128ab4350df9a8e1fb0f6b] +q_0_x_b: [0x0c4a20b16ab4ea905b4a89dfec08306108d5f78f5e128ab4350df9a8e1fb0f6b, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x097bb197473ac1cf61ebd9c570d5d19e239d22fb68f2d98c5aefc40b664dd612 0x053863e217745ee5315de73b00804817637e55fbbaa39f028a9e847e7a2cff93 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x1e888e574e2cba4a4719caf11db45b5daee94a77b7c1a2c1731e49636dd29818, 0x200de346ab90c61834b08b799ae402f1cf73d54b303cf3509b38c49f37f3737c, 0x08f4037c1190c53ab34b61c3cf2a4070943614b5af58f117aad0e512213a9467, 0x24ebc345f274e4d6e299b12b7e360e5c5f2d6e1a54a25e7660e77a35d918832a, 0x0aef4586845990202a4b9c1615be205dbf63ff6fb81d0353a82d9bed02e2c9b4, 0x2e7ff08acb56886037211cbc258ac282769cf2e7524c51623bb5f5794b47f954, 0x2e74a4c9797a473d9eb5c28f1df60d988c1ff42f42c2010a691c8148251afa63, 0x2e6b1cd51d249d2c2f575b683d2c3fbd66a3eda9a1a53ef03065a1a1363dcf77, 0x25c4dfcdf17fca3c9327cf04d6617365b73058b40384ef19f64296418ffea280, 0x1ec7d4f4edb4418acbc012e105a9baab45fd07e1cad5f9b7d0371e5503b1936d, 0x08b3e2fdad1f249e3130ed1a75d0f20166e66c572c52d2c5d66065ffaf34a91e, 0x1324c8cb563cacf45d48a6bc393b2dde55661e4489b358ed478882aa9953d62b, 0x19b9e9fdf2db9bd7114fa22dae701fda01cd9efb51d1193e49201d1338c73b60, 0x1804d964fcfe17be80788bb673da6b25804800f9ff15e11ffd3880829751bf6e, 0x0b1f7798ff9e1c634ff48d2a79562aa5925de3078eafb5ed47a294c2a25d7952, 0x20d034ddf756d51483c4495457115d79c0d7c7cc4996eef7284af32336154838, 0x2f890f9dc51f8df7935950362a8e088acc834a0d6a0faa04bb238cecc104231e, 0x0b1540e5d42130958840acb6bd4aec45e1643d5298e19610dc9303a7c7294009, 0x1a1f7fda83c78c73dba2d59edf737e5b8defa7349846743d54e23d67b77fb6fd, 0x12555f2fccc7acbafbc71cf040503ec29b906dd17c033454f83ad617a39544c5, 0x06149732e9d7767092c45f77c7c4e5dc0c81df1712a0855a5bc57440371c64e0, 0x17b9ad2a9435c2928090fff847c1b2776b82a3967ce2b5346981e05063d79a69, 0x2ef81053794a0f0184cea9b17dc5a3efdada4c81026c84bf868f045daf2a53a9, 0x21c5f9fb1afa68859eae08217734d821b2dcb0f5e80eaa17f07d12d8539da4ca, 0x05c991efe718e5c6d8969aa484efe40b9c66175d37a1540217d4cca5ee0301c9, 0x183bae5520e74c05f2841bed4905cbac80c20aae49a8ec43b459ae9de37aee86, 0x22788dafa9fda69b308791663d6c790aaefd781d22b4f8670833dc5e71e13ef1, 0x19e32f5cefb16632fa877ed2fe9abec900a8a5dcb2b8790a747d163453b3753b, 0x2069dce124659cc46d7320be8f3c6ecd22fbee5215127f7bc34ede3be24b7f62, 0x1909e30bf125b3a4980b35b82e74df15dc59a7f34f431b12536d6473e7b03ab5, 0x10a4e7eb070fc9483c3f5b5d5afabd8680d170779c58e0821a0503339232bd3a, 0x22a668137b940bb07fc551a90d7fae9245c810f87416a9991d6b4b2da66c4951], degree_0: 2, degree_1: 16 } +point: (0x02b6f1c28a6867330340743a4e6c6c35bef33a4fb1dbe12f763a2825c299e214, 0x21a6a654300c1b3abccb150fc1005e90869125ddde26708665331f381d665534) +f_x_b: [0x0544cfff506ef3e8cdfbfdb884da8a076138985b641728bbad3d24c1966022f7, 0x1ba7c3201c0b12ebf6420d5a5ccff082e296662af2002776880853cb1b785820] +q_0_x_b: [0x1ba7c3201c0b12ebf6420d5a5ccff082e296662af2002776880853cb1b785820, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x02b6f1c28a6867330340743a4e6c6c35bef33a4fb1dbe12f763a2825c299e214 0x21a6a654300c1b3abccb150fc1005e90869125ddde26708665331f381d665534 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x0587866fce70dc7eafd9eb1f56538824e1123f56be7ab63ba8182722c5988f31, 0x1b78327674de659a742b7ee3313a83fca24ba726d99e03e3a18270538a9051e4, 0x197dd1b6cdf20fc9e4f989f8131f5654b9b525127302fe13ef186eeb691d0b1f, 0x08553c563c55a7c25d91c29e9daa1732fdffd673fb9464c3886c35a46a27056f, 0x2ab29ae776746f0b2f3d934aa60cbaf6d3c515104ee2dc837688ec6bb793ab38, 0x08f16b967d1dc5c31d4ae0d16291e5c565f43c46d3c99c4412236c30873ff7d8, 0x1adb0fa420e4a9592cecf613c1c20b0782f65a1aff8298ede25a1174de8a6c53, 0x034171428a415a5058a6ac2a585c714d4d5db4602ae4fcfa2adb19ed48e91287, 0x14b446e3bbd9b87bd151b09ff8d2cda2451f08370e0f1826d7de39a9afdfaeb5, 0x1b9b8ae22d3696e5301db41966949fac52a9adab611f53a0763f5de5124aba99, 0x0b42454f74046f81a2d89b338833a07fc3d3f4e8af96cd42c26105706a8537d8, 0x14bf2d2f38ce3c29f9c4c1121da5f73805b1752df0f2860db6e4862647a4bd6b, 0x036aa9d554dd07c5ed92f5e06b574baa3eb9dda405cfc1b07b7a40ca6c7e481d, 0x1874a10808e191d8f530bcea8dbd1895578bf46e8cac216d582e7f10bb1a412a, 0x1304c10c133d8ba5e598a819db919e1860f05d6d29f5b592347120b558403ee9, 0x233e97150aa31ddc24a78a3bb873efe48b30f11b777a70042bb4ec068b2cfedd, 0x0c1b57ea10c480a8e434604b1b926a3adcd9f8b2550f14bb512b2a07f635120c, 0x22c92a035c1a088918f8ffd8c26ce24ac103dda98ee4cb2d8040abfeef37da0e, 0x03e42f5239e0ae4d18682c6bcde13af80c7b847c9d53bc59bd63cc4ebc66abc4, 0x0dcb011d97150267d65873d1dc736ef47798817abcce389f6408331b09430fca, 0x1f4fd972458a79d8a8aa852f3cfa0eb86bf56d7b4e838b4c77e4c50f1f3e66ba, 0x26082233ec917c6e3680de093128fd552c5ba0959afb49f4a1c84d630b930441, 0x2e5212f6ee546f6e99e30f4610fd7b8a9faba33da8872c1887f03a3aaf5052b8, 0x113fbe0a489b8fcef723b71b02c681400d00d7eae5f4bf94acc8b0ba2799714a, 0x0b235893abee48d7dc1ebf1285c5d084c1dabbe015cac0f338103954823d2d0c, 0x129c92b91b41399aa7dbd81a2a6f4fe8a890e1ddcd5606da824c4b1924fae0e7, 0x19e3a0e4c0660fbddd60f8ded0a22c5fe219c263c0e684d15f2b37fa9cb84ccb, 0x02ce5b2907aeab24a477ba3ec29e4a5c8742a7ea1470cd9ad2db4b9031ca461f, 0x22cb6f322d33f9a2e3f47490d4291ea9b37576a684e0eaded54a9af47aa2ff38, 0x01f9f8e183c022b78fbd910424adaf26a3a2ab0c9fb3a0c2293be83edac54025, 0x0f4ef93399d9ca4ad8e48a27fd42384c865b526142c4f08a523ddb232a681fbb, 0x24dd8d182fe12463611cfdffe626571b1202697c641c67aa4a6474896e989313], degree_0: 2, degree_1: 16 } +point: (0x27285a460340604b2b67f1a5e9b5e38a8a7dc2b6372a9a53f35109c95b6af5d8, 0x13e1a085481d82ff99a62f9b3f556c1ad7387f8fc4a23dd04b2f31e1323fa9fe) +f_x_b: [0x0f0b873d546e773e143d7f0e3115249d8dda75cf6ccbad0a5d29b9d138815ca2, 0x10167124ef7b4d41771165a25457a5d7fd8e16ed7ab46775260ea8b528b70908] +q_0_x_b: [0x10167124ef7b4d41771165a25457a5d7fd8e16ed7ab46775260ea8b528b70908, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x27285a460340604b2b67f1a5e9b5e38a8a7dc2b6372a9a53f35109c95b6af5d8 0x13e1a085481d82ff99a62f9b3f556c1ad7387f8fc4a23dd04b2f31e1323fa9fe +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x133fce514e68595c90d2e338ff67d8d09faa0032164dba5203c1c752e0b5f1cf, 0x1b68468b0acd361e74fedf161e4f24bd6497669b5cc63f030ffa1ca867ee54b8, 0x091e6fddb6686c88aad43c1ec771840fe9f80ae34472c06310f03c650fb89b5e, 0x1a13affaadfa6f5b6ab6f5a21f938d91e3ceb22def9b185c5a15eb5dd10c88ba, 0x2ccd5ea9cd76b81906d53f2e1c9a81f254705e2d7e0d52258717f501ec14916c, 0x0a8bb64fd33af846d32724c8f0b5ec06d293a722755fced2d3bf05f362b953a0, 0x168a3ab12dc1bd6d4d7bef302effadaac7092a9a1901ee15a38485b167004f93, 0x0c94fa8ee5d8cae8e0ec33bd3450405f44c55aca7be9b496cded959c0e065f09, 0x2b9e5efda23775bed9b86b9ab0ab6dce197ef161988702cba90402c117f74ef2, 0x24d0769819c7e43c9e58a29b16cc3392038644004b54b41c0d187e64b5a8d9b3, 0x0ac8113cbc70fce9a4b370ee90b4151d84d9a72dcc98d70ced531a8ee7e6240b, 0x163b9165b560e9378cade928ffd3490383a2a6a76fdd07fbe635242cfca97b61, 0x24f42a975c686b6c97446556828e887ac711c2ef6521595ae1ed2041d6a0ac74, 0x08f225ef6c5fe032f9209dc0b2c706ec9f3f9887816b47e322f9e3cd39c8cd26, 0x2bdc52fd8f3d6c8d7557e230a87bb5db26e0d18b64d4cfb71e204af3cfa82bab, 0x27bdae505e0704d86e69b01c1993b23d08fefa14dfdd0ac27a1b66e4cd1bc363, 0x05891cffaf777984cf9590c203cf3118c8c9a11a23967b14c1d0d25a039fb999, 0x12e32f501d4a07ca20eb104791f74b5e751b37e27dcb830668e230063c2d2098, 0x076982c787dc51c0cda90f0f4f7a6485ac10d64bfa4d059a0cc20aaef05ed4d9, 0x3060a4e5a6c24a2238776da7285451653c1d00b28724afdbf7c9b30d16415fe3, 0x0025f6ab2f6dd866c4b2dcf4e07d7ca5dfb7dcdf37ed5e4d7756341db1da0827, 0x302958988c9bde2b6c7e9890233a3f7de086424dd0629a7e933c7f561a1c1987, 0x18114b84ef2f507771f38fba5f04d9ccc7baeb6627e56ffd996a3f8a00f8cebd, 0x18c62c36fcadd8341bd23fdf2026bc14df5332d37a165be802727fa7be0d698c, 0x1b26c72c347405ddd8c27def98ea9cc043680545df7905b95d8a66860d9097dd, 0x01068dc569b3053f954bbb46c279abaaf6c88c65ea678a63873f8fde3d4d4efc, 0x2136a60df3d2e16f54323ddd3c5ae0b314af4891c9ce9b82c43419248452e76c, 0x2c16038dd752c6bc190e3767d135519c45705582d0c735752e0dd93ccb842ace, 0x1744c1e35b0907e7d2d2a1c2eef4e9361dc086ba77c41e768875e622a97d7955, 0x2aac5fe1873be682ef1fd60f3c22ad306692848564d7657f78711e51814cab38, 0x0cdb74b50c9407456cecaaed4d7b90b5700cbe4b54ad5c45c844b44f5077f529, 0x217ee24fb39716f1cd616e31f10b4176021986bda44433114cca297420b53621], degree_0: 2, degree_1: 16 } +point: (0x1fe37b904b445f7e080a9fb3329e055c6f97b5b745a506b873f6a300b1af5c12, 0x2bf6d103387fcb8639ec4395412ae7e802c8cd2b2eafed395f4a0c25c3bcada9) +f_x_b: [0x27050b6055483298f6bda71107482329ab2e8292d05c3427ca0e3c185c1ae8be, 0x1112e38ee715cbd75f9610318ce293845a426ba5769faa70e8659db97d33fa2f] +q_0_x_b: [0x1112e38ee715cbd75f9610318ce293845a426ba5769faa70e8659db97d33fa2f, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x1fe37b904b445f7e080a9fb3329e055c6f97b5b745a506b873f6a300b1af5c12 0x2bf6d103387fcb8639ec4395412ae7e802c8cd2b2eafed395f4a0c25c3bcada9 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x272b21593adf308e46a7127eebafab68c4a62cb7140855c47d16aeb6a9d8a692, 0x0752a810d112eab5be267fbf39740b8918978e709922aaf743e367f9332af679, 0x167ce43b3ab0f4b4c8ba0af4aad552bcd4e46f86e18fd2fd3f0f492c47baf72f, 0x2e41b06b7e5b462bedbe8c7c52cf15b02d9c668dc5e4af334e4f53073644a241, 0x035bb9516a7038466cc409847075aa16dab82ff9c9ded4d3ffc44c88231b9095, 0x1169be2ac06bdaf8e530d2a510bb2b9b966c2df16b100f39444d72061ea5a76e, 0x1950eccb727c17dc6d6afc578379d5af577b541339ce06296b9dc211b3727754, 0x2b37a862de5d4c39b39daf87c7281bb78151707a9fca1bb145999acbab737795, 0x2d5019ff9e719fa13f47bc4ff01b27f155e221b8af45a30ddf6bf77090b1e410, 0x03000d9af228ac0aebaf13f62e55b731d5431be9a4e5be487e1540c06bd7d619, 0x050ac7184eef8b29717066cffa9043d617f7784ad95876b7e2770baa6520dc9b, 0x050176f6c29587c06ae5e7c752875c8c36c7de15b43180f6c110bdaae9f0d960, 0x2832baf8e45b5e26a565f23a8bca6c0923a2ba5770946846b971f1289cfc605b, 0x2c487785e91c3804962fc36b442652ee68e2ab833efb9056a1e9befa29a30038, 0x00613a4a3f6789faf024357d5493d4b7c34083a1cfacaae60b0eda1bc729712d, 0x076d423fb0b614bc17b88bea081b29ba8330f85112947bc8b17f7e093977c958, 0x0f8f90904f899f3d3cc76d7d6cad9e1fe6436a0a84bf0dcdf7b8f189f683e6d8, 0x1cc312706f6e32d648675a37cfe0cd5079f141c32af08cdc2f1e41df4fbe0f7d, 0x1f952ca62cfc34ee412e66fd08e1502af9c5cd000ad19916a5fb17f48a2f7aa6, 0x1551b8b37307d42602f97a454b53844dfa0d41c4fd3b228cae081d4e2d63ff4c, 0x1729326b72efe292e8c25cde0efaaffc411ebb883bf61ce9d742866506118d1d, 0x1bcba450a5a7042bea1b1858b0ad0b576a05acd51e980121cb6ab630bb874d8e, 0x1362eb9880782aeaedfce9bf56780b29694dfe0f9db7eec72e1f8d876534de01, 0x26409e050da41f4f09c850e6bfc0241e8f1262b118d003c65d0e52654f9adbb2, 0x13a86bfc36bd62ac1d36c30fc41de110e62e151fe83fe2d2c355a1bd0fc62a2c, 0x174d0bd7068c8c62d3d6e364f39f9b49de76a84910ecf487c43ddce955efc54b, 0x1ddf7c0f9e931ea5c64de327b1e78c88d6fb0825638c1812d9f33eb0b98e0eee, 0x0aeb33204d1bb7a84d6482b83a50a1e33612e665566e68ba87da48c35cf1c7bc, 0x1c3a9fd437ed4caf26c593e495be7f92ee64d0af6e5e307b5c2ce742a13ca163, 0x1cd42e2cf58455c5a50ce3146f34c5531dfe89b26e55daf226112a6cf038b9fd, 0x190e56d0d04b932f3e19aa64ae228cfc1c887e9241c91b63c3cea00eef455a8f, 0x12ce323ab544e51e423738d7a41112653c62593752696ccc3a1aedba910a0b3b], degree_0: 2, degree_1: 16 } +point: (0x244a46d9d45fc65ca474eaa732170b850dcd6696aa889161c9abbcc63d9e8972, 0x0bec7961dee23536cb071da46c63d28e5c8aca6225ca60406c7379961718fb9b) +f_x_b: [0x225b8322aaa243f04d96dacd8c10458263fe13d8ab94821f41d8d706d62462cc, 0x2b1101dc879ed398144e846c3d9dfe5d5e3bde2cea4a564c3b9ad0737c673941] +q_0_x_b: [0x2b1101dc879ed398144e846c3d9dfe5d5e3bde2cea4a564c3b9ad0737c673941, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x244a46d9d45fc65ca474eaa732170b850dcd6696aa889161c9abbcc63d9e8972 0x0bec7961dee23536cb071da46c63d28e5c8aca6225ca60406c7379961718fb9b +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x23c826d686e1110e290ea5a793228436d8466984ee53c37f1725f54ac1cd29e1, 0x27582862e1b0b95e4f56ef61258d3184d289515423c583a7bac901a3c1322a92, 0x2e8772a7cb985b1dbefa75edb29bdd4835c3d1f040c2e44b4051dc678802aa2a, 0x0379b1031fbee625acc4d86264f6d64cc8617edd10e091ec1dd7fca0aad2dc4f, 0x0b40732f816caaeea649a78b40b1d70f5aa9a31e46e968f3370f1687ee994193, 0x22800560cdb0d43b963f878c6698595fbe85bbb01788a6b4eaaa299245f4534a, 0x08e3b6d1e49df33dae1fc9cab8abb2ecc5eca659455763cad8aa58860e164edc, 0x1b36ecd2e0d7e0796a507309340a64a09acae4dd9aa0055d585dbc27eaa923a1, 0x21785d97572539cffe411cbb67657ddf6c89851689152264ab181fb12e7f4ad9, 0x194d359acc8f21d08523d571ebe14013442f059306250d290b9760924310be54, 0x088e9130ca95bdca74bfdf3539634ff811a9b756370e54028742470824e339c0, 0x18ec1f2d0d0de969792361b837765acaf3d356482e022025d9f5841f600390a4, 0x246d8d13602c5f830c8316ee9b11087dced2d19e56ecd5d6c9d10cb39ef80d2f, 0x0c26d4742f74f7adc81e059db1e21936452ef966a8371618f3e68188e39d1bab, 0x20d6735e2277c77fe4ebecbfbd0bdad9851cac7ee4525c5e19a995e65b60f349, 0x13c751ed9030085a206461f542c3eb43932cdc5ad798abd508f37dde8c37e0be, 0x107e6fd381b7571dd89ea969879d8967d4d6c039ed11b5b1e13b9cae079446a8, 0x1d49865d6b3e5e58da877022553c2b73b81e309b60815735634d5df2f13a1009, 0x0b887d676e126acabbca02864b162f630ae6953d7b4bfe76f12046e0fa95f643, 0x0218123eddefe2fbd0e5f390ed3c8a0d9d53182819f3b108ca1c0ad19f441f4c, 0x0f7952d85274d258733c8354b19f7162370cf1ca8428711ae818b8f2062fee63, 0x238cf87b935516e8e791da8e339e13ea7a2baffca4960c607d4146d6a911a040, 0x289f1a0d192b8160c33f3b4d0089944d0a6ed7b86a359bb942ab0b3b69a52b05, 0x0e8e5cd651a1c825d3dc41e2d289e6af150376a4fdb49ead5a414f54a45786bc, 0x2c268dbf9b93d317e2d79dca97d5055dfb4340a303145181fb043198bf489c39, 0x29b5905fc62f9c1836d316d5fa40c888fa310253d3f6422ed5f1b07c1e0d19ae, 0x1ab5623fa0a708ba16b88c49f696d3d0e2812f8820ae9c2e1b8c73ee7bddb9d7, 0x1a3b37cdd6bbb635c746d7da346d7d5342727552b4325aae86575691da207d19, 0x29f793e9f8588abe68c9edbb50ecf07a91fb65e9f71b52e12a2cc452fb1dd549, 0x2fabe6d759bbda917bab91eb63b7b30faa64319b925f15ec6eb2e9ca69bafc71, 0x09661c78abc59ffa32778a87831a1d23dfb5659065bfc61e02af7c3ffa0cd28e, 0x02756e86f36e49f45a7c73a2ca2279e4e544a2b9e49fe3f22b577a5a729cd9ba], degree_0: 2, degree_1: 16 } +point: (0x0358a2c426aa1b2f82caa46a093f14d97bcade8195afce1ed6920fbbd582894b, 0x2a0551807ff813f25d13b2b3669d1a7b530a0745dcb645ecc41bed9ac39c66f2) +f_x_b: [0x222a0fbfd1e333952588a7b0daedb10fb5f34f83f6bf769f06983475c7172dbe, 0x05a7533986644f32ae3691ef9c9f4608f9218b20d8acd23b6102d7dbae53e839] +q_0_x_b: [0x05a7533986644f32ae3691ef9c9f4608f9218b20d8acd23b6102d7dbae53e839, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x0358a2c426aa1b2f82caa46a093f14d97bcade8195afce1ed6920fbbd582894b 0x2a0551807ff813f25d13b2b3669d1a7b530a0745dcb645ecc41bed9ac39c66f2 +here2 +res: true +finished commit +poly: BivariatePolynomial { coefficients: [0x0f9535d4df4d9d66dc15ac3872cf9172c63ea8b5fd4324eb9e97d2110a22ee35, 0x284c64d51d06ff00f142964a4a3565015be1bf5c47a6a22fa669b7ba62677b1e, 0x26625c83126acb143fbd446d27e60d1eed469e9b59dc4150166455b3783b39c0, 0x0fd8c1734d6221cca4e42a1cf3e1144d9bd33b41a2af16d622bab590d647e063, 0x15828eaefd591dcc8a7fd5c474a977be951f6570b345a91e9080d6d8f8626309, 0x1820c8dad6e11e2b6fba8a13dafbc405a4b8615c7a91da0bf6f65e8247fe67a0, 0x24163aca790d878c272a72233ec45546c54d6dce8b8cf5c52be1bf8fe0f966f9, 0x1fc43a336c25849e4154bd104c15e8abbd8d9d7ad3cc4b1eaf2b998bca699a81, 0x14cdad523e75ab82bc77b55528c2e2ad185094fe30e1524dc0d30d19644a4cb9, 0x1640e54569f9f2e2b20af6f4c89a4e98f0c191b71e0bee141a854183e50655e3, 0x2f19b8db7ed8a6224b93627eab26773e02b17f87b10cb70ce3a420388a724c30, 0x2afc8396ffa251714811abb634532688919bd87470355707ec643c407041f2b9, 0x1b167a4cb3709bd5f3dfdcb8eee9506b1f0d69b0e7d7296b4d734f1a050a38b8, 0x13b2bdb76c3bfe3275910524a7bb610ec8c31a8068a1693458e95bd1b96f455b, 0x16ce4dab4d8700b595fe344944866e431aa41e66414de52db864a521421e5b35, 0x21788a2a0133359def27e48f934be18260d8d0b84be0ad5be3e77494c8b962f2, 0x00b68ba4f2cac785e1abe87fe9c4c385ce71b6e8ebe3edb23ccf666781eabc27, 0x0509b5131c056c2f671d5c4faa006086f239c665911bde430e12e5da454a0edb, 0x0497ae245d563364fb512aa5a0fe1b58f8f21c7fa64461d8018eec94b5afe112, 0x03cc2007da1db84c7bf7629f54eec10f585228d08e01a446ab063e38448c64a6, 0x19e0f845eb7f72eefbf7f4ea74ec56dd5f3152a1e9dfc6f769d3557f2ba02fd7, 0x1ece2ba9d6196e6a73cf1979f87c37d0a62ff564403fff7b77b0f212879632da, 0x255b15a1b34fd72c2ab5d0be2049c7f279435f3cfb3300547c47d6452e2e8bdc, 0x03b1b7904b326049019befab0e0884560909008d0b94ec7ade4847bfdcbea91f, 0x0488e5af6be58cab5ff153b8f660e161cfbe343a0ba4c77244e534385d89c768, 0x0c92ddbf675350df778f10f2732a9cf73780c1c47f66c1536092a79c6cdf3b9a, 0x1a946914887ea21477b7a20f34cb68c325d651c5b89fafcf313a6562d6888fb5, 0x2781ae8293b75bb14bd4202389fc1e1aac0a05081e853eb7a8a4c1281c7ab476, 0x1314f4883bfef1cc59af8111fcf9040add7873d71e2d364c6568cd148f58ecf4, 0x1cbb43bd130a22a3f7f356d257cac29b943990867dc46ed0ac3b6b127685d9b0, 0x1aa30082ceb28f106a5db12cdf870eafaab92f2d44b015486a0099c873ca118c, 0x2bfd29b664259f3eb3b14d24914ceaaff1dff99f1ab9c2369c0922a7e7c8a65b], degree_0: 2, degree_1: 16 } +point: (0x06b9752431ff00c7c5c83f86ad2f9929a91cd9bd869f58bc5846affd22e20fd9, 0x2c42b3443c3cfd584f37ecc147152b339ee69100227366286ce95623b04377fe) +f_x_b: [0x2cdd1cf6e187f5b1b517149aaff35a68e15e2485135bd77bd6d5752a06ae737e, 0x162a07c10432c5751d600749bdc2d2b8ec21f83864dc0741eb70b528d2989ff1] +q_0_x_b: [0x162a07c10432c5751d600749bdc2d2b8ec21f83864dc0741eb70b528d2989ff1, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x06b9752431ff00c7c5c83f86ad2f9929a91cd9bd869f58bc5846affd22e20fd9 0x2c42b3443c3cfd584f37ecc147152b339ee69100227366286ce95623b04377fe +here2 +res: true +m: 2, n: 4 +omega 0: 0x30644e72e131a029048b6e193fd841045cea24f6fd736bec231204708f703636 +omega 1: 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000 +n: 4 +m: 2 +start to compute the scalars +f_x_b_scalars: [0x0000000000000000000000000000000000000000000000000000000000000138, 0x30644e72e1319f812fc62248f2fb751e930ccbe3f81515c280efe4696932d181, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff31, 0x00000000000000a8888a236d8e85e33e95271c6481a45acec2f2112a86cd2e20] +lagrange scalars: [0x000000000000000000000000000000000000000000000000000000000000009c, 0x30644e72e1319fd5740b33ffba3e66bddda05a1638e74329e268ecfeac9968c1, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff99, 0x0000000000000054444511b6c742f19f4a938e3240d22d676179089543669710, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff8c, 0x000000000000003f3333cd491572353777eeaaa5b09da20d891ac66ff28cf170, 0x000000000000000000000000000000000000000000000000000000000000004e, 0x30644e72e1319fea851c786d6c0f2325b0453da2c91bce83bac72f23fd730eb5] +start to compute the affine bases +start to compute the lagrange bases +lagrange scalars: [0x000000000000000000000000000000000000000000000000000000000000009c, 0x30644e72e1319fd5740b33ffba3e66bddda05a1638e74329e268ecfeac9968c1, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff99, 0x0000000000000054444511b6c742f19f4a938e3240d22d676179089543669710, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff8c, 0x000000000000003f3333cd491572353777eeaaa5b09da20d891ac66ff28cf170, 0x000000000000000000000000000000000000000000000000000000000000004e, 0x30644e72e1319fea851c786d6c0f2325b0453da2c91bce83bac72f23fd730eb5] +finished commit +poly: BivariatePolynomial { coefficients: [0x22f570bef606bed65c7096c6a0c817e609afcfe713ba31147f8bd51b251cabeb, 0x0507ca135e47bffb64abd5ae3354a7bfdb3153434c930089dd662b20932fc330, 0x21fa0dd9f736b1f3a1a3c04aac2531ac09644d652db07c85eaeb64fa7d6e19dd, 0x23e83443e10a4ff4ab587f214216873c3fc8c6ed9f0d3bc6765a3e33825c4a27, 0x0620576f0f43be5090f4454fa5a86123628037e211520624fff8f4e060146af4, 0x2ce9baa1967d600ca9df7cca0b75f47318fc3ed448d3948930d148cef30a837f, 0x03c948203ef5a50473a68eb3f20d5ed12b1866c106d62aef7c8eced2275ef406, 0x2b19eea023ee966c87bfbf6490c791577e9c015e3a07afb209000e7190f4afee], degree_0: 4, degree_1: 2 } +point: (0x287b052408f6442905491ad99116c3d6e15673ef933dc3ee05bd02b22cf1a598, 0x0e495ae92321aac79e9db2666cc509872a1b9890585320b2c11c257b701ae079) +f_x_b: [0x0e892e919ac142923a9c14b04fe1977064b57df066909bb9f504329f07d2ce95, 0x15aa88702ff4eeffdb2918b1398ed54ac7a82021a3af554afbd21e40c277c745, 0x206ae4ddcfd8b46f3d6eac253f3be7c872a46a64c262ef6fa80d87420722cf8c, 0x06f1006603a0f604cdcecc6a96cf33764cb551649fd1dc571a9c504c7f645bad] +q_0_x_b: [0x1a7b6dc7ce5e3ccf739e2fff825616f7cc2098a6b46b9bc5936695e27ed31fc0, 0x2852fb8eed333e5fcdcae12f91da1192728f21178f9dba779f576e74ccf47365, 0x06f1006603a0f604cdcecc6a96cf33764cb551649fd1dc571a9c504c7f645bad, 0x0000000000000000000000000000000000000000000000000000000000000000] +here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x287b052408f6442905491ad99116c3d6e15673ef933dc3ee05bd02b22cf1a598 0x0e495ae92321aac79e9db2666cc509872a1b9890585320b2c11c257b701ae079 +here2 +thread 'tests::test_bi_kzg_e2e' panicked at bi-kzg/src/bi_kzg.rs:391:9: +assertion `left == right` failed: pi0 != pi_0 + left: (0x1b348c4ea8e9dccc02afa645ba5258ec4184946b58a2364d074e1452cdc59eb8, 0x187841463bf7b9da9a37dfa89b522fa46b66f54402180167989c6a07c0ec8ecf) + right: (0x011d7aa1d767c13eec64a8649a3a9eff5311382528f17b2d0beef5f31a4b4445, 0x1df89f82500251aeb91db0705eb725afa27afec0b4b0f81988dcbeab060264cc) note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace failures: tests::test_bi_kzg_e2e -test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 3 filtered out; finished in 0.00s +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 6 filtered out; finished in 0.13s diff --git a/bi-kzg/script/lagrange.sage b/bi-kzg/script/lagrange.sage index 999ed298..591fc089 100644 --- a/bi-kzg/script/lagrange.sage +++ b/bi-kzg/script/lagrange.sage @@ -109,4 +109,17 @@ print(f_rec) t_rec = P(0) for i in range(8): t_rec += bases[i] * t_lag[i] -print(t_rec) \ No newline at end of file +print(t_rec) + + +#poly: BivariatePolynomial { coefficients: [0x22f570bef606bed65c7096c6a0c817e609afcfe713ba31147f8bd51b251cabeb, 0x0507ca135e47bffb64abd5ae3354a7bfdb3153434c930089dd662b20932fc330, 0x21fa0dd9f736b1f3a1a3c04aac2531ac09644d652db07c85eaeb64fa7d6e19dd, 0x23e83443e10a4ff4ab587f214216873c3fc8c6ed9f0d3bc6765a3e33825c4a27, 0x0620576f0f43be5090f4454fa5a86123628037e211520624fff8f4e060146af4, 0x2ce9baa1967d600ca9df7cca0b75f47318fc3ed448d3948930d148cef30a837f, 0x03c948203ef5a50473a68eb3f20d5ed12b1866c106d62aef7c8eced2275ef406, 0x2b19eea023ee966c87bfbf6490c791577e9c015e3a07afb209000e7190f4afee], degree_0: 4, degree_1: 2 } +#point: (0x287b052408f6442905491ad99116c3d6e15673ef933dc3ee05bd02b22cf1a598, 0x0e495ae92321aac79e9db2666cc509872a1b9890585320b2c11c257b701ae079) +#f_x_b: [0x0e892e919ac142923a9c14b04fe1977064b57df066909bb9f504329f07d2ce95, 0x15aa88702ff4eeffdb2918b1398ed54ac7a82021a3af554afbd21e40c277c745, 0x206ae4ddcfd8b46f3d6eac253f3be7c872a46a64c262ef6fa80d87420722cf8c, 0x06f1006603a0f604cdcecc6a96cf33764cb551649fd1dc571a9c504c7f645bad] +#q_0_x_b: [0x1a7b6dc7ce5e3ccf739e2fff825616f7cc2098a6b46b9bc5936695e27ed31fc0, 0x2852fb8eed333e5fcdcae12f91da1192728f21178f9dba779f576e74ccf47365, 0x06f1006603a0f604cdcecc6a96cf33764cb551649fd1dc571a9c504c7f645bad, 0x0000000000000000000000000000000000000000000000000000000000000000] + + +p = P(0x22f570bef606bed65c7096c6a0c817e609afcfe713ba31147f8bd51b251cabeb + 0x0507ca135e47bffb64abd5ae3354a7bfdb3153434c930089dd662b20932fc330*x + 0x21fa0dd9f736b1f3a1a3c04aac2531ac09644d652db07c85eaeb64fa7d6e19dd*x^2 + 0x23e83443e10a4ff4ab587f214216873c3fc8c6ed9f0d3bc6765a3e33825c4a27*x^3 + 0x0620576f0f43be5090f4454fa5a86123628037e211520624fff8f4e060146af4 * y + 0x2ce9baa1967d600ca9df7cca0b75f47318fc3ed448d3948930d148cef30a837f*x*y+ 0x03c948203ef5a50473a68eb3f20d5ed12b1866c106d62aef7c8eced2275ef406*x^2*y + 0x2b19eea023ee966c87bfbf6490c791577e9c015e3a07afb209000e7190f4afee *x^3*y) + +px = p(x, 0x0e495ae92321aac79e9db2666cc509872a1b9890585320b2c11c257b701ae079) + +f = P(0x0e892e919ac142923a9c14b04fe1977064b57df066909bb9f504329f07d2ce95 + 0x15aa88702ff4eeffdb2918b1398ed54ac7a82021a3af554afbd21e40c277c745*x + 0x206ae4ddcfd8b46f3d6eac253f3be7c872a46a64c262ef6fa80d87420722cf8c*x^2 + 0x06f1006603a0f604cdcecc6a96cf33764cb551649fd1dc571a9c504c7f645bad*x^3) \ No newline at end of file diff --git a/bi-kzg/src/bi_kzg.rs b/bi-kzg/src/bi_kzg.rs index c2662e05..416664a0 100644 --- a/bi-kzg/src/bi_kzg.rs +++ b/bi-kzg/src/bi_kzg.rs @@ -250,9 +250,23 @@ where polynomial: &Self::Polynomial, point: &Self::Point, ) -> (Self::Proof, Self::Evaluation) { + // fixme + let tau_0 = prover_param.borrow().tau_0; + let tau_1 = prover_param.borrow().tau_1; + let a = point.0; + let b = point.1; + let c = polynomial.evaluate(&tau_0, &tau_1); + let u = polynomial.evaluate(&a, &b); let (pi_0, f_x_b) = { let f_x_b = polynomial.evaluate_y(&point.1); - let q_0_x_b = univariate_quotient(&f_x_b, &point.1); + let mut q_0__x_b = f_x_b.clone(); + q_0__x_b[0] -= u; + let q_0_x_b = univariate_quotient(&q_0__x_b, &point.0); + println!("poly: {:?}", polynomial); + println!("point: {:?}", point); + println!("f_x_b: {:?}", f_x_b); + println!("q_0_x_b: {:?}", q_0_x_b); + let pi_0 = best_multiexp( &q_0_x_b, // prover_param.borrow().f_x_b_scalars.as_ref(), @@ -262,13 +276,6 @@ where (pi_0, f_x_b) }; - // fixme - let tau_0 = prover_param.borrow().tau_0; - let tau_1 = prover_param.borrow().tau_1; - let a = point.0; - let b = point.1; - let c = polynomial.evaluate(&tau_0, &tau_1); - let u = polynomial.evaluate(&a, &b); // let u_prime = polynomial.evaluate(&tau_0, &b); let pi_1 = { let mut t = polynomial.clone(); From db88d32fd87473dd0a72c2e605cbbc239f6977b8 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Thu, 13 Jun 2024 22:34:53 -0400 Subject: [PATCH 18/31] clean up --- bi-kzg/benches/bi_kzg_bench.rs | 4 +- bi-kzg/src/bi_kzg.rs | 177 +++------------------------------ bi-kzg/src/pcs.rs | 6 +- bi-kzg/src/poly.rs | 46 ++++----- bi-kzg/src/structs.rs | 26 ++--- bi-kzg/src/tests.rs | 3 - bi-kzg/src/util.rs | 2 +- 7 files changed, 45 insertions(+), 219 deletions(-) diff --git a/bi-kzg/benches/bi_kzg_bench.rs b/bi-kzg/benches/bi_kzg_bench.rs index 464e46b5..c5e687dc 100644 --- a/bi-kzg/benches/bi_kzg_bench.rs +++ b/bi-kzg/benches/bi_kzg_bench.rs @@ -1,5 +1,4 @@ use ark_bn254::{Fr, G1Affine, G1Projective}; -use ark_ec::short_weierstrass::Projective; use ark_ec::Group; use ark_ec::{AffineRepr, VariableBaseMSM}; use ark_ff::Zero; @@ -7,10 +6,9 @@ use ark_ff::{PrimeField, UniformRand}; use halo2curves::bn256; use halo2curves::ff::Field; use halo2curves::msm::best_multiexp; -use rand::Rng; use std::{thread, time::Duration}; -use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use criterion::{criterion_group, criterion_main, Criterion}; fn criterion_benchmark(c: &mut Criterion) { let degree_set = vec![2048, 4096, 8192, 16384]; diff --git a/bi-kzg/src/bi_kzg.rs b/bi-kzg/src/bi_kzg.rs index 416664a0..5b619f27 100644 --- a/bi-kzg/src/bi_kzg.rs +++ b/bi-kzg/src/bi_kzg.rs @@ -1,21 +1,13 @@ -use std::ops::{Add, AddAssign}; -use std::process::Output; -use std::thread; -use std::{borrow::Borrow, marker::PhantomData, slice::ChunkBy}; +use std::ops::Add; +use std::{borrow::Borrow, marker::PhantomData}; use halo2curves::ff::Field; use halo2curves::ff::PrimeField; -use halo2curves::fft::best_fft; use halo2curves::group::prime::PrimeCurveAffine; use halo2curves::group::Curve; use halo2curves::group::Group; - -// use halo2curves::msm::best_multiexp; use halo2curves::pairing::{MillerLoopResult, MultiMillerLoop}; -use halo2curves::pasta::pallas::Scalar; -use halo2curves::CurveAffine; use itertools::Itertools; -use rand::Rng; use rand::RngCore; use crate::msm::best_multiexp; @@ -54,10 +46,10 @@ where assert!(supported_n.is_power_of_two()); assert!(supported_m.is_power_of_two()); - // let tau_0 = E::Fr::random(&mut rng); - // let tau_1 = E::Fr::random(&mut rng); - let tau_0 = E::Fr::from(5); - let tau_1 = E::Fr::from(7); + let tau_0 = E::Fr::random(&mut rng); + let tau_1 = E::Fr::random(&mut rng); + // let tau_0 = E::Fr::from(5); + // let tau_1 = E::Fr::from(7); let g1 = E::G1Affine::generator(); @@ -67,12 +59,6 @@ where let omega_0 = omega.pow_vartime(&[(1 << E::Fr::S) / supported_n as u64]); let omega_1 = omega.pow_vartime(&[(1 << E::Fr::S) / supported_m as u64]); - println!("omega 0: {:?}", omega_0); - println!("omega 1: {:?}", omega_1); - - println!("n: {}", supported_n); - println!("m: {}", supported_m); - assert!( omega_0.pow_vartime(&[supported_n as u64]) == E::Fr::ONE, "omega_0 is not root of unity for supported_n" @@ -86,7 +72,7 @@ where println!("start to compute the scalars"); // computes the vector of L_i^N(tau_0) * L_j^M(tau_1) for i in 0..supported_n and j in 0..supported_m - let (scalars, f_x_b_scalars, lagrange_scalars) = { + let (scalars, lagrange_scalars) = { let powers_of_omega_0 = powers_of_field_elements(&omega_0, supported_n); let powers_of_tau_0 = powers_of_field_elements(&tau_0, supported_n); let lagrange_tau_0 = lagrange_coefficients(&powers_of_omega_0, &tau_0); @@ -96,22 +82,9 @@ where let scalars = tensor_product_parallel(&powers_of_tau_0, &powers_of_tau_1); let lagrange_scalars = tensor_product_parallel(&lagrange_tau_0, &lagrange_tau_1); - let mut f_x_b_scalars = lagrange_tau_0.clone(); - powers_of_tau_1.iter().skip(1).for_each(|bi| { - f_x_b_scalars - .iter_mut() - .zip(lagrange_tau_0.iter()) - .for_each(|(fi, li)| *fi += *bi * *li); - }); - - println!("f_x_b_scalars: {:?}", f_x_b_scalars); - - (scalars, f_x_b_scalars, lagrange_scalars) - // (scalars, powers_of_tau_0, lagrange_scalars) + (scalars, lagrange_scalars) }; - println!("lagrange scalars: {:?} ", lagrange_scalars); - println!("start to compute the affine bases"); let coeff_bases = { let mut proj_bases = vec![E::G1::identity(); supported_n * supported_m]; @@ -132,27 +105,6 @@ where println!("start to compute the lagrange bases"); - let f_x_b_scalars = { - let mut proj_bases = vec![E::G1::identity(); supported_n]; - parallelize(&mut proj_bases, |g, start| { - for (idx, g) in g.iter_mut().enumerate() { - let offset = start + idx; - *g = g1 * f_x_b_scalars[offset]; - } - }); - - let mut affine_bases = vec![E::G1Affine::identity(); supported_n]; - parallelize(&mut affine_bases, |affine_bases, starts| { - E::G1::batch_normalize( - &proj_bases[starts..(starts + affine_bases.len())], - affine_bases, - ); - }); - drop(proj_bases); - affine_bases - }; - - println!("lagrange scalars: {:?} ", lagrange_scalars); let lagrange_bases = { let mut proj_bases = vec![E::G1::identity(); supported_n * supported_m]; parallelize(&mut proj_bases, |g, start| { @@ -176,10 +128,7 @@ where // assert_eq!(coeff_bases[..supported_n], f_x_b_scalars); BiKZGSRS { - tau_0, - tau_1, powers_of_g: coeff_bases, - f_x_b_scalars: f_x_b_scalars, powers_of_g_lagrange_over_both_roots: lagrange_bases, h: E::G2Affine::generator(), tau_0_h: (E::G2Affine::generator() * tau_0).into(), @@ -205,13 +154,7 @@ where ) .into(); - assert_eq!( - com, - (prover_param.borrow().powers_of_g[0] - * poly.evaluate(&prover_param.borrow().tau_0, &prover_param.borrow().tau_1)) - .into(), - "commitment is not equal to evaluation" - ); + #[cfg(test)] { let lag_coeff = poly.lagrange_coeffs(); let com_lag = best_multiexp( @@ -228,20 +171,6 @@ where ); } - { - let lag_coeff = poly.evaluate_y(&prover_param.borrow().tau_1); - let com_lag = best_multiexp( - &lag_coeff, - prover_param.borrow().powers_of_g[..poly.degree_0].as_ref(), - ) - .into(); - assert_eq!( - com, com_lag, - "commitment is not equal to lagrange commitment" - ); - } - - println!("finished commit"); Self::Commitment { com } } @@ -250,36 +179,26 @@ where polynomial: &Self::Polynomial, point: &Self::Point, ) -> (Self::Proof, Self::Evaluation) { - // fixme - let tau_0 = prover_param.borrow().tau_0; - let tau_1 = prover_param.borrow().tau_1; let a = point.0; let b = point.1; - let c = polynomial.evaluate(&tau_0, &tau_1); let u = polynomial.evaluate(&a, &b); + let (pi_0, f_x_b) = { let f_x_b = polynomial.evaluate_y(&point.1); - let mut q_0__x_b = f_x_b.clone(); - q_0__x_b[0] -= u; - let q_0_x_b = univariate_quotient(&q_0__x_b, &point.0); - println!("poly: {:?}", polynomial); - println!("point: {:?}", point); - println!("f_x_b: {:?}", f_x_b); - println!("q_0_x_b: {:?}", q_0_x_b); + let mut q_0_x_b = f_x_b.clone(); + q_0_x_b[0] -= u; + let q_0_x_b = univariate_quotient(&q_0_x_b, &point.0); let pi_0 = best_multiexp( &q_0_x_b, - // prover_param.borrow().f_x_b_scalars.as_ref(), prover_param.borrow().powers_of_g[..polynomial.degree_0].as_ref(), ) .to_affine(); (pi_0, f_x_b) }; - // let u_prime = polynomial.evaluate(&tau_0, &b); let pi_1 = { let mut t = polynomial.clone(); - // t.coefficients[0] -= u_prime; t.coefficients .iter_mut() .take(polynomial.degree_0) @@ -293,33 +212,19 @@ where let divisor = BivariatePolynomial::new(divisor, polynomial.degree_0, polynomial.degree_1); - // let omega = E::Fr::ROOT_OF_UNITY; - // let omega_1 = omega.pow_vartime(&[(1 << E::Fr::S) / polynomial.degree_1 as u64]); - // let divisor = fft_slow(divisor.as_ref(), &omega_1); let divisor = divisor.lagrange_coeffs(); - // let omega = E::Fr::ROOT_OF_UNITY; - // let omega_1 = omega.pow_vartime(&[(1 << E::Fr::S) / polynomial.degree_1 as u64]); - // let powers_of_omega_1 = powers_of_field_elements(&omega_1, polynomial.degree_1); - // todo: batch invert let y_minus_a_inv_lag = divisor .iter() .map(|o| { if o.is_zero_vartime() { - // E::Fr::ZERO panic!("not invertible") } else { o.invert().unwrap() } }) .collect::>(); - // let mut q_1_x_y = vec![]; - // for i in 0..polynomial.degree_0 { - // for j in 0..polynomial.degree_1{ - // q_1_x_y.push((coeffs[j*polynomial.degree_0 + i] - f_x_b[i]) * y_minus_a_inv_lag[j]); - // } - // } let q_1_x_y = coeffs .iter() @@ -336,64 +241,9 @@ where .as_ref(), ) .to_affine() - // // let domain = Domain::::new_for_size(prover_param.borrow().powers_of_g_lagrange_over_both_roots.len() as u64).unwrap(); - - // let bases = prover_param.borrow().powers_of_g_lagrange_over_both_roots.as_slice(); - // let mut q_1_x_y = vec![]; - // let lag_bases = (0..polynomial.degree_0*polynomial.degree_1).map(|i|E::Fr::from(i as u64)). collect::>(); - // let mut cb = vec![E::Fr::from(0);polynomial.degree_0*polynomial.degree_1]; - // for i in 0..1 { - // let start = 0; - // let mut end = polynomial.degree_0; - // if end > polynomial.degree_0 {end = polynomial.degree_0;} - // let handle = thread::spawn(move || { - // // let cb_ptr = cb_ptr_usize as *mut E::Fr; - // // let mut lag_base_ptr = lag_base_ptr_usize as *const Fr; - // // lag_base_ptr = unsafe { lag_base_ptr.offset((start * degree_m) as isize)}; - // for j in start..end { - // let mut cj = vec![E::Fr::from(0);polynomial.degree_0]; - // // lag_base_ptr = unsafe { lag_base_ptr.offset(degree_m as isize)}; - // // domain1.ifft_in_place(&mut cj); - // best_fft(&mut cj, ); - - // let mut cb_temp = cj[degree_m-1]; - // unsafe{ cb_ptr.add(j*degree_m + degree_m - 1).write(cb_temp) }; - // for k in (1..(degree_m-1)).rev() { - // cb_temp *= b; - // cb_temp += cj[k]; - // unsafe{ cb_ptr.add(j*degree_m + k).write(cb_temp) }; - // } - // } - // }); - // handles.push(handle); - // } }; - // let u = polynomial.evaluate(&a, &b); - let u_prime = polynomial.evaluate(&tau_0, &b); - - let f_tau0_b = polynomial.evaluate(&tau_0, &b); - let f_a_tau1 = polynomial.evaluate(&a, &tau_1); - - println!("here {:?} {:?} {:?} {:?}", tau_0, tau_1, a, b); - let q_0 = (f_tau0_b - u) * ((tau_0 - a).invert().unwrap()); - let q_1 = (c - u_prime) * ((tau_1 - b).invert().unwrap()); - - println!("here2"); let proof = BiKZGProof:: { - pi0: (prover_param.borrow().powers_of_g[0] * q_0).into(), - pi1: (prover_param.borrow().powers_of_g[0] * q_1).into(), - }; - - let t0 = q_0 * (tau_0 - a); - let t1 = q_1 * (tau_1 - b); - let right = c - u; - - assert_eq!(t0 + t1, right, "t0 + t1 != right"); - assert_eq!(pi_0, proof.pi0, "pi0 != pi_0"); - assert_eq!(pi_1, proof.pi1, "pi1 != pi_1"); - - let proof2 = BiKZGProof:: { pi0: pi_0, pi1: pi_1, }; @@ -428,7 +278,6 @@ where ]); let res = res.final_exponentiation().is_identity().into(); - println!("res: {:?}", res); res } diff --git a/bi-kzg/src/pcs.rs b/bi-kzg/src/pcs.rs index 4a3fee9d..cb54a764 100644 --- a/bi-kzg/src/pcs.rs +++ b/bi-kzg/src/pcs.rs @@ -1,7 +1,7 @@ -use std::{borrow::Borrow, fmt::Debug, hash::Hash}; +use std::{borrow::Borrow, fmt::Debug}; -use halo2curves::{ff::Field, pairing::Engine, serde::SerdeObject}; -use rand::{Rng, RngCore}; +use halo2curves::{ff::Field, serde::SerdeObject}; +use rand::RngCore; /// This trait defines APIs for polynomial commitment schemes. /// Note that for our usage of PCS, we do not require the hiding property. diff --git a/bi-kzg/src/poly.rs b/bi-kzg/src/poly.rs index 8f4730f0..794ea003 100644 --- a/bi-kzg/src/poly.rs +++ b/bi-kzg/src/poly.rs @@ -2,7 +2,6 @@ use halo2curves::ff::{Field, PrimeField}; use itertools::Itertools; use rand::RngCore; use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; -use rayon::vec; use crate::structs::{BivariateLagrangePolynomial, BivariatePolynomial}; use crate::util::powers_of_field_elements; @@ -78,11 +77,6 @@ impl BivariatePolynomial { }; let powers_of_omega_0 = powers_of_field_elements(&omega_0, self.degree_0); let powers_of_omega_1 = powers_of_field_elements(&omega_1, self.degree_1); - // println!( - // "omega len {} {}", - // powers_of_omega_0.len(), - // powers_of_omega_1.len() - // ); // Todo! Optimize me. This is not efficient. let mut res = vec![]; @@ -91,15 +85,10 @@ impl BivariatePolynomial { res.push(self.evaluate(omega_0_power, omega_1_power)); } } - // println!("powers_of_omega_1: {:?}", powers_of_omega_1); - // println!("res: {:?}", res); + res } - // pub fn from_lagrange_coeffs(coeffs: Vec, degree_0: usize, degree_1: usize) -> Self { - // assert_eq!(coeffs.len(), degree_0 * degree_1); - // todo!() - // } } /// For x in points, compute the Lagrange coefficients at x given the roots. @@ -210,7 +199,7 @@ impl From> for BivariateLagrangePolynomial } impl From> for BivariatePolynomial { - fn from(poly: BivariateLagrangePolynomial) -> Self { + fn from(_poly: BivariateLagrangePolynomial) -> Self { todo!() } } @@ -320,21 +309,21 @@ mod tests { let eval_at_y = poly.evaluate_y(&Fr::from(10u64)); assert_eq!(eval_at_y, vec![Fr::from(7531u64), Fr::from(8642u64)]); - let poly = BivariatePolynomial::new( - vec![ - Fr::from(1u64), - Fr::from(0u64), - Fr::from(1u64), - Fr::from(0u64), - Fr::from(0u64), - Fr::from(0u64), - Fr::from(0u64), - Fr::from(0u64), - ], - 2, - 4, - ); - println!("poly: {:?}", poly.lagrange_coeffs()); + // let poly = BivariatePolynomial::new( + // vec![ + // Fr::from(1u64), + // Fr::from(0u64), + // Fr::from(1u64), + // Fr::from(0u64), + // Fr::from(0u64), + // Fr::from(0u64), + // Fr::from(0u64), + // Fr::from(0u64), + // ], + // 2, + // 4, + // ); + // println!("poly: {:?}", poly.lagrange_coeffs()); } #[test] @@ -410,7 +399,6 @@ mod tests { // 0x0000000000000000000000000000000000000000000000000000000000000000, // 0x30644e72e131a0241a2988cc74389d96cde5cdbc97894b683d626c78eb81b1a1, // 0x0000000000000000000000000000000000000000000000000000000000000000] - println!("lag: {:?}", lagrange_coeffs); assert_eq!(lagrange_coeffs.len(), 8); assert_eq!( format!("{:?}", lagrange_coeffs[0]), diff --git a/bi-kzg/src/structs.rs b/bi-kzg/src/structs.rs index f6f2999e..eea62a42 100644 --- a/bi-kzg/src/structs.rs +++ b/bi-kzg/src/structs.rs @@ -19,10 +19,6 @@ pub struct BivariateLagrangePolynomial { /// Structured reference string for Bi-KZG polynomial commitment scheme. #[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct BiKZGSRS { - // FIXME: remove me - pub tau_0: E::Fr, - pub tau_1: E::Fr, - /// (g_1^{\tau_0^i\tau_1^j})_{i\in [0,N], j\in [0, M]} = \\ /// ( /// g_1, g_1^{\tau_0}, g_1^{\tau_0^2}, ..., g_1^{\tau_0^N}, @@ -30,8 +26,6 @@ pub struct BiKZGSRS { /// ..., g_1^{\tau_0^N\tau_1^M} /// ) pub powers_of_g: Vec, - /// g in lagrange form over omega_0 - pub f_x_b_scalars: Vec, /// g in lagrange form over omega_0 and omega_1 pub powers_of_g_lagrange_over_both_roots: Vec, /// The generator of G2. @@ -95,10 +89,10 @@ impl SerdeObject for BiKZGCommitment { /// to ensure the bytes represent a valid object. As such this function should only be /// used internally as an extension of machine memory. It should not be used to deserialize /// externally provided data. - fn from_raw_bytes_unchecked(bytes: &[u8]) -> Self { + fn from_raw_bytes_unchecked(_bytes: &[u8]) -> Self { todo!("Implement this function") } - fn from_raw_bytes(bytes: &[u8]) -> Option { + fn from_raw_bytes(_bytes: &[u8]) -> Option { todo!("Implement this function") } @@ -111,14 +105,14 @@ impl SerdeObject for BiKZGCommitment { /// to ensure the bytes represent a valid object. This function should only be used /// internally when some machine state cannot be kept in memory (e.g., between runs) /// and needs to be reloaded as quickly as possible. - fn read_raw_unchecked(reader: &mut R) -> Self { + fn read_raw_unchecked(_reader: &mut R) -> Self { todo!("Implement this function") } - fn read_raw(reader: &mut R) -> io::Result { + fn read_raw(_reader: &mut R) -> io::Result { todo!("Implement this function") } - fn write_raw(&self, writer: &mut W) -> io::Result<()> { + fn write_raw(&self, _writer: &mut W) -> io::Result<()> { todo!("Implement this function") } } @@ -129,10 +123,10 @@ impl SerdeObject for BiKZGProof { /// to ensure the bytes represent a valid object. As such this function should only be /// used internally as an extension of machine memory. It should not be used to deserialize /// externally provided data. - fn from_raw_bytes_unchecked(bytes: &[u8]) -> Self { + fn from_raw_bytes_unchecked(_bytes: &[u8]) -> Self { todo!("Implement this function") } - fn from_raw_bytes(bytes: &[u8]) -> Option { + fn from_raw_bytes(_bytes: &[u8]) -> Option { todo!("Implement this function") } @@ -145,14 +139,14 @@ impl SerdeObject for BiKZGProof { /// to ensure the bytes represent a valid object. This function should only be used /// internally when some machine state cannot be kept in memory (e.g., between runs) /// and needs to be reloaded as quickly as possible. - fn read_raw_unchecked(reader: &mut R) -> Self { + fn read_raw_unchecked(_reader: &mut R) -> Self { todo!("Implement this function") } - fn read_raw(reader: &mut R) -> io::Result { + fn read_raw(_reader: &mut R) -> io::Result { todo!("Implement this function") } - fn write_raw(&self, writer: &mut W) -> io::Result<()> { + fn write_raw(&self, _writer: &mut W) -> io::Result<()> { todo!("Implement this function") } } diff --git a/bi-kzg/src/tests.rs b/bi-kzg/src/tests.rs index 5f881c68..1e4ca6a0 100644 --- a/bi-kzg/src/tests.rs +++ b/bi-kzg/src/tests.rs @@ -37,8 +37,6 @@ fn test_bi_kzg_e2e() { assert_eq!(poly.evaluate(&x, &y), Fr::from(85309u64)); - println!("poly lag coeff: {:?}", poly.lagrange_coeffs()); - let commit = BiKZG::::commit(&srs, &poly); let (proof, eval) = BiKZG::::open(&srs, &poly, &(x, y)); @@ -46,7 +44,6 @@ fn test_bi_kzg_e2e() { for n in [2, 4, 8, 16] { for m in [2, 4, 8, 16] { - println!("m: {}, n: {}", m, n); let srs = BiKZG::::gen_srs_for_testing(&mut rng, n, m); let vk = BiKZGVerifierParam::::from(&srs); for _ in 0..10 { diff --git a/bi-kzg/src/util.rs b/bi-kzg/src/util.rs index 377a482b..d539b323 100644 --- a/bi-kzg/src/util.rs +++ b/bi-kzg/src/util.rs @@ -1,5 +1,5 @@ use halo2curves::ff::Field; -use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; +use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; pub(crate) fn powers_of_field_elements(x: &F, n: usize) -> Vec { let mut powers = vec![F::ONE]; From 102fa61b4e57407fd270f25cf1405df286f1da9e Mon Sep 17 00:00:00 2001 From: zhenfei Date: Thu, 13 Jun 2024 22:36:40 -0400 Subject: [PATCH 19/31] clean up --- bi-kzg/1.log | 420 --------------------------------------------------- 1 file changed, 420 deletions(-) delete mode 100644 bi-kzg/1.log diff --git a/bi-kzg/1.log b/bi-kzg/1.log deleted file mode 100644 index 443ac0ed..00000000 --- a/bi-kzg/1.log +++ /dev/null @@ -1,420 +0,0 @@ - -running 1 test -test tests::test_bi_kzg_e2e ... FAILED - -failures: - ----- tests::test_bi_kzg_e2e stdout ---- -omega 0: 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000 -omega 1: 0x30644e72e131a029048b6e193fd841045cea24f6fd736bec231204708f703636 -n: 2 -m: 4 -start to compute the scalars -f_x_b_scalars: [0x00000000000000000000000000000000000000000000000000000000000004b0, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffce1] -lagrange scalars: [0x000000000000000000000000000000000000000000000000000000000000012c, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff39, 0x30644e72e1319f78c28c06e9df0e5cf50b97a41224ccde04f73096c0e2755c09, 0x0000000000000075f92d7f3316f7524568682d798df30c5d88763f375e5c6d50, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff20, 0x0000000000000000000000000000000000000000000000000000000000000096, 0x00000000000000b0f5c43ecca272fb681c9c443654ec928c4cb15ed30d8aa3b0, 0x30644e72e1319fb3bf22c6836a8a0617bfcbbaceebc66433bb6bb65c91a392e1] -start to compute the affine bases -start to compute the lagrange bases -lagrange scalars: [0x000000000000000000000000000000000000000000000000000000000000012c, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff39, 0x30644e72e1319f78c28c06e9df0e5cf50b97a41224ccde04f73096c0e2755c09, 0x0000000000000075f92d7f3316f7524568682d798df30c5d88763f375e5c6d50, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff20, 0x0000000000000000000000000000000000000000000000000000000000000096, 0x00000000000000b0f5c43ecca272fb681c9c443654ec928c4cb15ed30d8aa3b0, 0x30644e72e1319fb3bf22c6836a8a0617bfcbbaceebc66433bb6bb65c91a392e1] -poly lag coeff: [0x0000000000000000000000000000000000000000000000000000000000000024, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffffd, 0x00000000000000059e26bcea0d48bac65a4e1a8be2302529067f891b047e4e50, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff9, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x30644e72e131a0241a2988cc74389d96cde5cdbc97894b683d626c78eb81b1a1, 0x0000000000000000000000000000000000000000000000000000000000000000] -finished commit -poly: BivariatePolynomial { coefficients: [0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000003, 0x0000000000000000000000000000000000000000000000000000000000000004, 0x0000000000000000000000000000000000000000000000000000000000000005, 0x0000000000000000000000000000000000000000000000000000000000000006, 0x0000000000000000000000000000000000000000000000000000000000000007, 0x0000000000000000000000000000000000000000000000000000000000000008], degree_0: 2, degree_1: 4 } -point: (0x0000000000000000000000000000000000000000000000000000000000000009, 0x000000000000000000000000000000000000000000000000000000000000000a) -f_x_b: [0x0000000000000000000000000000000000000000000000000000000000001d6b, 0x00000000000000000000000000000000000000000000000000000000000021c2] -q_0_x_b: [0x00000000000000000000000000000000000000000000000000000000000021c2, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x0000000000000000000000000000000000000000000000000000000000000009 0x000000000000000000000000000000000000000000000000000000000000000a -here2 -res: true -m: 2, n: 2 -omega 0: 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000 -omega 1: 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000 -n: 2 -m: 2 -start to compute the scalars -f_x_b_scalars: [0x0000000000000000000000000000000000000000000000000000000000000018, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff1] -lagrange scalars: [0x000000000000000000000000000000000000000000000000000000000000000c, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff9, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff8, 0x0000000000000000000000000000000000000000000000000000000000000006] -start to compute the affine bases -start to compute the lagrange bases -lagrange scalars: [0x000000000000000000000000000000000000000000000000000000000000000c, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff9, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff8, 0x0000000000000000000000000000000000000000000000000000000000000006] -finished commit -poly: BivariatePolynomial { coefficients: [0x28529920e40112fe2e9d58c0db300a98ad3d5231b5e69e8adf414654474a982b, 0x01ea7f4579ced4124c477515e0f2de62da874c3ec078b59912b98dba52ed7853, 0x1a6124422f756ba9e16761c1d95d295a2b14267f1266f04d91a603466934532a, 0x16f7715e31ed1c4c4b910916fb0d4b41457cd7580d187742d8afebaddb4cd73b], degree_0: 2, degree_1: 2 } -point: (0x292e552a4945289f77eeabb9cd9caaa98caec50805b10b6d5c5a7b5a302252f3, 0x1c8603896a992e6063e301fd68eaa34780850235549b590b3cff365c58a0568d) -f_x_b: [0x04b6dad76a64c12a220c3c0832d51fdeb7cd7fd17798dd080842731639e4f849, 0x224af4b667ed288ee97b44d76add61c46e4be3bd934df9ad21c55b0d2e8d8b62] -q_0_x_b: [0x224af4b667ed288ee97b44d76add61c46e4be3bd934df9ad21c55b0d2e8d8b62, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x292e552a4945289f77eeabb9cd9caaa98caec50805b10b6d5c5a7b5a302252f3 0x1c8603896a992e6063e301fd68eaa34780850235549b590b3cff365c58a0568d -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x0e82cc355069b60a7ccf99b9154107826b75751f88ddbd1e07d69fbddaceff3b, 0x082e61c11f858d95cad2cc66e141c97998d679fedd1c784e19f09596b0646989, 0x0896062fad6c3cabff665b3b9de75306ea6217c38841b479988c7428a3943e4b, 0x07126d3e656fc3fc22c108056eccb6d55ee931e2c86055e096be9210988f71a1], degree_0: 2, degree_1: 2 } -point: (0x151956dca0bab6306d06fee3a08f916470b6fc0f5d284fb2e58891f8d4dfb4d6, 0x26bd54d45efd19ff17533e99cf70209627f2c342e4e2aab664ea3d52cd44c32a) -f_x_b: [0x152134071879cc123b24dc146283f106de447282132e8d8e8aa5c0850531778d, 0x196b4b11b62e9528b9911d042f7d6ea3186ee87bb699365b806af320a27c6573] -q_0_x_b: [0x196b4b11b62e9528b9911d042f7d6ea3186ee87bb699365b806af320a27c6573, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x151956dca0bab6306d06fee3a08f916470b6fc0f5d284fb2e58891f8d4dfb4d6 0x26bd54d45efd19ff17533e99cf70209627f2c342e4e2aab664ea3d52cd44c32a -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x031df8a22d2f9c1168f02a9c9c343334586ce820147711e918c16ce9e372115d, 0x11e48d19c1365c51686d2df7086e59158f78275b9f5a39f0c9886baebd345afa, 0x2f0a41e02aee0467a1e41d95677e26136e4c8dc0973d93211fdb4ee4d3884bba, 0x182caea2e22bbfa372f5f1ac6594484344ee3c4c1b3ff547d1b5b1bbdf3820ac], degree_0: 2, degree_1: 2 } -point: (0x0b82797c2e7a97dd307c4af3fd386fdac96cd7d1ba745a325c0b1c3db9a6c890, 0x114c0145a86181a3f83748ba901316c4fc752112080d081c80b704fdb0f25d74) -f_x_b: [0x0a565042f563c2e3e28b43cb99a5f31d57603d8606289d8635733fa2c55975e0, 0x05e4ad539f5fb22a26f2b0c3c81e34748308f8eb5242b6eb34e4414adc9c8e03] -q_0_x_b: [0x05e4ad539f5fb22a26f2b0c3c81e34748308f8eb5242b6eb34e4414adc9c8e03, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x0b82797c2e7a97dd307c4af3fd386fdac96cd7d1ba745a325c0b1c3db9a6c890 0x114c0145a86181a3f83748ba901316c4fc752112080d081c80b704fdb0f25d74 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x136ddb1c61e5d4d246f571a1ed2d78e64d6c074f7e93733f95599b33644df7ea, 0x04492380d843c40545dd3100066314d10743769b3be9274853f5ec58c0db1a9c, 0x2c89839003fb91afaed6507e07b899f15e28775c8609bc272ea2f6da0edb9f18, 0x1d0ff87b13d7e9ecc80eb284d8c776a5a1d4dc861aa3c18513a839bb230d5b63], degree_0: 2, degree_1: 2 } -point: (0x005d82805494b3c3fbcef176e48ca0227fe082aff6fcb847be30c4e00334cde6, 0x2ac47771fc4a8f19f6f17db67fe170bcfc944af8620d4a253a5c4f138d449c79) -f_x_b: [0x14de3b150b3fa45e7177abbb3eb55eae7119543dcfa2ecca0192e21b0b792d35, 0x187aa1946c0013d0e32833b9a57b9a0d55eaea6d56ca8f2b6bdf24bdc4c82c8d] -q_0_x_b: [0x187aa1946c0013d0e32833b9a57b9a0d55eaea6d56ca8f2b6bdf24bdc4c82c8d, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x005d82805494b3c3fbcef176e48ca0227fe082aff6fcb847be30c4e00334cde6 0x2ac47771fc4a8f19f6f17db67fe170bcfc944af8620d4a253a5c4f138d449c79 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x1bbe64bf201e36337b37164817708b1ec8186718f87f6579f7f02cb2c22ee38b, 0x1b37374da26a3a0b9c707c492d214a22717c51ea143616310a7517b5eb4c80e7, 0x19fdc820bdd8193f88e3dac5fabb2b923bedaa88c983839d12a7a728987ecf29, 0x27ca00dfcf1ecc882023ad7bab845d2f70478e51b4ff15a633c86db03b6d762b], degree_0: 2, degree_1: 2 } -point: (0x0415e4367921908bfa498d497b8a176f5ff755d750fa1de26d5360e014eaec43, 0x19da74ab07ad91055e5d984af7914a32a52d05ed9feeeac5ba69aa9ffb45a708) -f_x_b: [0x22addd03640c5a86c0f26e3cee4f40981f0e573d0e600a58082768ef7cd0829b, 0x191a608fe6c134c56fe2047b4bc43f3431fda751eb4b4cd2d34d4eeecc5ae537] -q_0_x_b: [0x191a608fe6c134c56fe2047b4bc43f3431fda751eb4b4cd2d34d4eeecc5ae537, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x0415e4367921908bfa498d497b8a176f5ff755d750fa1de26d5360e014eaec43 0x19da74ab07ad91055e5d984af7914a32a52d05ed9feeeac5ba69aa9ffb45a708 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x0b8fc6c1e14bb35e2a1d7885c2338514ed95d83b177a08fc6eb23f23d311a1f7, 0x0df9d50ed9f841e70b00a70163588b180dde0648de4b5f43d74964ae235f884e, 0x1d7fc0ca88e60d38fb0e49ee50cb63551d51359896fd5fea6f9243372db2da22, 0x0c3c57a5dc6da870646fc519919b89faee66077b1dbb85ac753d0e761e0a6c6c], degree_0: 2, degree_1: 2 } -point: (0x1162a28d882117feca6126fce44365d987b37ae52822142626198b740af416ad, 0x172db215c90780c364f6b3d54013d39f1c9ebb9e046f6911a84e059a370c1c8d) -f_x_b: [0x213ae76092e2c685adb84495b6a9413fa36ff983aa25f888b07683bd8893cddf, 0x13cd08f138ef0c5138aabacabd373fbffe0866403de2544a85b51c7d274b319f] -q_0_x_b: [0x13cd08f138ef0c5138aabacabd373fbffe0866403de2544a85b51c7d274b319f, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x1162a28d882117feca6126fce44365d987b37ae52822142626198b740af416ad 0x172db215c90780c364f6b3d54013d39f1c9ebb9e046f6911a84e059a370c1c8d -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x2133fc92389e143749df33c69863b635ee37de497343aebb47ab96fe4df2c228, 0x21b7d97511b224719bc16f0eb8825660849f8cc1958743515f0adfd674aeb4e4, 0x00543c11ad2b2bc9eb3874b4f83b4b67c1700216a620f23ce7a652a79e2bd05b, 0x2bd9af20c1d34e5bc3f06d091fd3dfadc413ed5926bbf457f9c7b9f91d28ca62], degree_0: 2, degree_1: 2 } -point: (0x2d250b31f0af7167fbb9ee5bda8f3b519fd2c400bcea759d0e780353121ec514, 0x01f3f20c8aa0c397f72d34d16ac09e2d5a0bb06bbfc2621d5766604969780c3f) -f_x_b: [0x18e7a9a70a24c9d207cb79fc1f609e756b659234afc995cfcb373ea96380a40c, 0x1b0f353d6d50f4b86139a5faf0bb0ea55387a7f8ec7ce3981f8541c5343a1566] -q_0_x_b: [0x1b0f353d6d50f4b86139a5faf0bb0ea55387a7f8ec7ce3981f8541c5343a1566, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x2d250b31f0af7167fbb9ee5bda8f3b519fd2c400bcea759d0e780353121ec514 0x01f3f20c8aa0c397f72d34d16ac09e2d5a0bb06bbfc2621d5766604969780c3f -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x172412359106e3433cb2434c0f37e10adcc27e741f7ea8384a8c8f70510cd72c, 0x2ec6af4f75e83641d4336d6eccfde558ca886a761111bd489bd555678b5ce9c3, 0x176878d232207eec8be262ceb970bf5c690346f6175dcb6d2193d15526529165, 0x22e5004514ec403917bc1acd85af83aae773247991872fdd299e9cc703d7ccda], degree_0: 2, degree_1: 2 } -point: (0x1f613dac90f9f2639d877d7866f30f62795f2f23a7b2710827c6bb80a804bed6, 0x1e402abf7cd6960b5538a4ae1e14f2fcb383a4ac413ef191c231b7aa5e841047) -f_x_b: [0x19ff6ece138e7b8e49c8fee5946d91cf91fa3fbd84fb63328aeb4a373cc3be87, 0x0fcae70e1fb3b03399cfb7c8cd83adce26bd5ac8b80019e4f5fa4d9b48ed2252] -q_0_x_b: [0x0fcae70e1fb3b03399cfb7c8cd83adce26bd5ac8b80019e4f5fa4d9b48ed2252, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x1f613dac90f9f2639d877d7866f30f62795f2f23a7b2710827c6bb80a804bed6 0x1e402abf7cd6960b5538a4ae1e14f2fcb383a4ac413ef191c231b7aa5e841047 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x13703c6d8902ba2db2e3ffa3beb77aa60fe80aa7b35a56cc95a859fb06f25386, 0x13631fb9023e6d9b76798a9b33b678064f07d2bbde1e6f3d26f1a6a73036a2a9, 0x041cf8010644cda62d5b7b917e57aa04e91d6a05fad2d8b0c349e5b0248087aa, 0x28c85887e02a4aa3dfb71c917efdc3035af7efeaa0f54854cffc1cfdaf39b992], degree_0: 2, degree_1: 2 } -point: (0x0c8e1daa01383e7da069758dbd90f1ab05f7d9f56e1dd0e586f963af61cc1af3, 0x09ecd5a6c3cc9083f93758733722251ad730a12c3e52696c345325fb566f219c) -f_x_b: [0x22cf20b8785f15b10635f6b33a313b774c2b72824d0c0df4f366db9ac70e06a2, 0x002702c6de401a78485ca3b316cbe2642f2855cd658c6dd95e3cd8307fc745e3] -q_0_x_b: [0x002702c6de401a78485ca3b316cbe2642f2855cd658c6dd95e3cd8307fc745e3, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x0c8e1daa01383e7da069758dbd90f1ab05f7d9f56e1dd0e586f963af61cc1af3 0x09ecd5a6c3cc9083f93758733722251ad730a12c3e52696c345325fb566f219c -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x2d66bb0e3ec7085598e0b253d89cccd6c0d0132f53f3560cd2b93106a6c896be, 0x116b4afb036ab74dba2713e9d26976ea38d0a2ae2bef45ba9dc56feffff28511, 0x1cabad80e674607bd69620c156e3764e8b7091c94d919eb2d63aae4ea1a1810d, 0x11329b11af9cf77998ad2e329762dded99806f1d2c883abd254f6f0a1e90b765], degree_0: 2, degree_1: 2 } -point: (0x12bde00976700c254b4d94bf42cdba0aa19c89a13261ed3a186a2ba2de0c24aa, 0x1831d67f1931bc74751fdbf6a26d36f095e2a70dffbd6fc33b6c1fb97c3a60cd) -f_x_b: [0x17eb9a41733d35f102c68e68f81ff9953bbc88985839bdf8bf5ca14cefdfedf3, 0x0d895abd38ab978ed29ac28320e604954ebd43faa73502720d2c9aa932dc3a02] -q_0_x_b: [0x0d895abd38ab978ed29ac28320e604954ebd43faa73502720d2c9aa932dc3a02, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x12bde00976700c254b4d94bf42cdba0aa19c89a13261ed3a186a2ba2de0c24aa 0x1831d67f1931bc74751fdbf6a26d36f095e2a70dffbd6fc33b6c1fb97c3a60cd -here2 -res: true -m: 4, n: 2 -omega 0: 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000 -omega 1: 0x30644e72e131a029048b6e193fd841045cea24f6fd736bec231204708f703636 -n: 2 -m: 4 -start to compute the scalars -f_x_b_scalars: [0x00000000000000000000000000000000000000000000000000000000000004b0, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffce1] -lagrange scalars: [0x000000000000000000000000000000000000000000000000000000000000012c, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff39, 0x30644e72e1319f78c28c06e9df0e5cf50b97a41224ccde04f73096c0e2755c09, 0x0000000000000075f92d7f3316f7524568682d798df30c5d88763f375e5c6d50, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff20, 0x0000000000000000000000000000000000000000000000000000000000000096, 0x00000000000000b0f5c43ecca272fb681c9c443654ec928c4cb15ed30d8aa3b0, 0x30644e72e1319fb3bf22c6836a8a0617bfcbbaceebc66433bb6bb65c91a392e1] -start to compute the affine bases -start to compute the lagrange bases -lagrange scalars: [0x000000000000000000000000000000000000000000000000000000000000012c, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff39, 0x30644e72e1319f78c28c06e9df0e5cf50b97a41224ccde04f73096c0e2755c09, 0x0000000000000075f92d7f3316f7524568682d798df30c5d88763f375e5c6d50, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff20, 0x0000000000000000000000000000000000000000000000000000000000000096, 0x00000000000000b0f5c43ecca272fb681c9c443654ec928c4cb15ed30d8aa3b0, 0x30644e72e1319fb3bf22c6836a8a0617bfcbbaceebc66433bb6bb65c91a392e1] -finished commit -poly: BivariatePolynomial { coefficients: [0x11c7e0e35e67d2828d28120fabcce980fdba8d58c1212bc0868bde8a084de9dd, 0x01c0c488bd03681c55098a7868aaaec94cfd1779c90de238a988c0d0399d0ada, 0x2c0bafa9dff55a23a67a81b6eb2c04dc4c719bb2deee00125b58089128ba7315, 0x2c99d65965843b34f978f316e6632a9a47e87e7cf0055ca728c0a674d3c380c6, 0x0a9f1f3f3378e25fcf7a814c0dc30f660481c6f0fcc207361ff06f3c91f29251, 0x03a77999bec9ab4ed4ea6fcfc29c66e999d51f32be0ccd02fff0241d8f30e04e, 0x2b2d14dcb2cb1336d8245fd5c41c315741bc79bf85da6fdbb1452fc91af120f4, 0x10b23cfa73f5659038976f93035a5222d7a5ece9f5f78f8b87f433df1eb445ea], degree_0: 2, degree_1: 4 } -point: (0x13be5805568b552a932b2b7a5cb7933f2db351b21998e67930418f4059e3fd31, 0x22f811b162a994df97f0a146cab2a27146d6dc8706c906f432102611ed6ba97a) -f_x_b: [0x0f52a6364d703a9bab1ad1165cfb946a4c7848cd8873e2fe57a02fbdafbb1882, 0x2be43aea9602b9371e49708e0ecaab958359816e03a549aaaaf06346119aee61] -q_0_x_b: [0x2be43aea9602b9371e49708e0ecaab958359816e03a549aaaaf06346119aee61, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x13be5805568b552a932b2b7a5cb7933f2db351b21998e67930418f4059e3fd31 0x22f811b162a994df97f0a146cab2a27146d6dc8706c906f432102611ed6ba97a -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x2a62b49cc9b4b54e496f3025bb47877b1a0d303d18d284840169c57e6c5337a4, 0x0101bd6111aea9671f80d0d278eeb30953a4ffa8056c2700e6d8da90247bda11, 0x29e57399e473c2c00c0536b27d0cc51b28d6e340f1c4472c4b7493daf1f5d8b4, 0x2bf669c024f457a9214c9d915601123ab0d28a839b09c8e13627716ef5c800c6, 0x08df965406a43ea3e5150df888e0997d6bf05b6e8d283a46f08589da52cdb081, 0x23e5695daff42298d80c7168d0a69fb5f78fe4ea05bab9e0bc15c0bf8111c52f, 0x22d36548a3b0a8f731cf917009cdce7298a7870bd183ba63a1985169c86719b4, 0x2d6ee202e5311f5bdd62ea4a570f8f504514a4f9de16b4c9061462f3158f3750], degree_0: 2, degree_1: 4 } -point: (0x1baf2028415add9831d922e5778bafc6183a56ca78cf5f881992470fa4571df2, 0x1db796a9b4dd6543979cd69d85762bd80856503b29551de3069994411c548692) -f_x_b: [0x0d38c5405d15edce2969a0356e87b5f15deaf04628e7f976a3c809de1519f5c7, 0x06895dc1df9108729df28144f7be2ebe9048f5bc5336451ae577acc156676551] -q_0_x_b: [0x06895dc1df9108729df28144f7be2ebe9048f5bc5336451ae577acc156676551, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x1baf2028415add9831d922e5778bafc6183a56ca78cf5f881992470fa4571df2 0x1db796a9b4dd6543979cd69d85762bd80856503b29551de3069994411c548692 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x04f297af9b2cd89b11eb6bbc0b8dd27f3b73680e058a9470d5718ed4b5532094, 0x25a6033c31e5e828a56ed6323e6709732350dd3c57661ef3f2bdbb23c510fc91, 0x1fee75cec3cb52e078ed2bdbe8da6131dbb4a5238d6b6dd10fc84f9cb2c1b959, 0x05e37e452061da5d289d44b8153b46b9069ab1dfc938791a24b9671189feeeaf, 0x0797d6753438b249dc553c460cd87fd3d910e8670cb94c8b94ca030468be5f61, 0x0dd2d750461d588473fc872882a456adc5757d118305f62346ce73a32bc579d0, 0x0909545e9bb9985fc8e78f4e72041c9747bfc82baf23bb1c074b96faeec0208c, 0x2b9e9dc1d047dedb159b224aef4cdb0d71c6fd19f73a356e4f811442eddb446c], degree_0: 2, degree_1: 4 } -point: (0x19a479d3ce4ab407099bc8cd68b689e33bdd7bbe4593cb163f7af1108a970c30, 0x2f2331603c17c7c0e0b66a4f50f088e3cbc3560d64b8a42a5dba9628046831b6) -f_x_b: [0x270957b44cdd23d985ab7263ab89f489958ab0f68447c75287a5d2fc32458f44, 0x01876e0f41917ff0a9247b2ebef35e021adbafb582f9303aa9cef471cbd10a6f] -q_0_x_b: [0x01876e0f41917ff0a9247b2ebef35e021adbafb582f9303aa9cef471cbd10a6f, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x19a479d3ce4ab407099bc8cd68b689e33bdd7bbe4593cb163f7af1108a970c30 0x2f2331603c17c7c0e0b66a4f50f088e3cbc3560d64b8a42a5dba9628046831b6 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x1547b7b863825dea8170d012837ebe218ef15a1664152f625af07ddc1cb8f7a2, 0x17f93f74519569559404f7ea10b620e0bd742ea6fce901192789bf61bda91879, 0x02d04b1de0c0a79db0f9e36a9efdf1d4b065bcc60ef309a070be752c53be7f6f, 0x163f4165230cfae0294b3f765a3ab61c6d92f6b8ad39beff29ae2de9171a84d3, 0x016452d89eca22e34f22de18b1f839513501b1096e72861f6d711168eaacf964, 0x0a36fa057199699a8d93d2c76dec84eb358faec2b1a831f9d418ea4e0532245e, 0x0883b2c7cefd49e2367bae89f76ce8be70fcdb827f41e9d332a2f8e91764325e, 0x29da4281d56be059705e6638e9ed295d7830a680878b2471c8f8baeb3cbe1c28], degree_0: 2, degree_1: 4 } -point: (0x1a7b6aebeb2048555b9c922ffdac0ee626d19a94c408e6550b69c5bb38bba214, 0x25216819a7d1e8284be43aa7b00d6aa42209c858ddbc7c053a1304d0ee1ba68a) -f_x_b: [0x282d4a7571e78eee01d6724b22a2401eef846b5b35fa93e48dd05be52d818122, 0x11e45d8696d912949ea8fdb2f3d71679e31e401b39093682204ce37e5f324d62] -q_0_x_b: [0x11e45d8696d912949ea8fdb2f3d71679e31e401b39093682204ce37e5f324d62, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x1a7b6aebeb2048555b9c922ffdac0ee626d19a94c408e6550b69c5bb38bba214 0x25216819a7d1e8284be43aa7b00d6aa42209c858ddbc7c053a1304d0ee1ba68a -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x08f1bfcba4ac26a07c4fcaee1e4d858452b4329060b7b8cad9dcc85cff3ad983, 0x001e0893b7ee1e08c937ed05b6a55bc89e75df0ab66c9324a2639e0d5385c9ea, 0x042b78728556911fe7848262031b4ff833b10375918f30ac674e4b1902dafe34, 0x066fbd2fc079b7c6079bee88fd6f82c8c6de0dc995b500e828f040d6a4d839a0, 0x03b2f6e1e31f860b883d35d77c5086f4d17ea93a7d7cab6a52618eb1fb4eb3f5, 0x2f607d7262220b5b78dd08668e4303e9c37abe8e85c655b00f2a629d0b461042, 0x0d984f2f83db8f03720ca31338e8d1f5fd3a203dd30164a5f123d31a52192239, 0x1ea202e7bb52a58976991788a3cd92273dc79f8c8b4e52382b83fa5d71916197], degree_0: 2, degree_1: 4 } -point: (0x1da88ccb70fd3c2c5efe5c6ded48545c828fe6b73b8e1c2a3b1c32af3e72d78d, 0x052c1d7f0b50a353bcd47abf8a00fee17824efbdffe0f2779d051607cc8a1d2a) -f_x_b: [0x29384a10fa9d7f13c472f373cb2969b67b355cec8281a8d07e33a3b9d470d68e, 0x07c5c565353d2b226e873378de2ecd9e3c1289ac2a075f7e00dcee4102998729] -q_0_x_b: [0x07c5c565353d2b226e873378de2ecd9e3c1289ac2a075f7e00dcee4102998729, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x1da88ccb70fd3c2c5efe5c6ded48545c828fe6b73b8e1c2a3b1c32af3e72d78d 0x052c1d7f0b50a353bcd47abf8a00fee17824efbdffe0f2779d051607cc8a1d2a -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x203897642af395a09433e03fbf8bca17c57c250951ba2bcf9686e991189a4a79, 0x21a161a5b62a3be76ecae44ffb92b422135039cb04f2668a4441d10db25ed5fc, 0x0dd66d8c0eea90daa3248a2d6711f1a23cb2d54de7247fe8cb69c6033e8689c1, 0x0e082aa6c2773bac642483865590488c00d04661e047ad7389174de9e0dbe35e, 0x0caf3795e7210e5feaa6145bd919b18b41ae4a2b2feeccc1e8c002687a1d1ae8, 0x108d05451d92b30bf67bb741e2f858e103fe55de124ea07a40ce90cfc42bcde9, 0x286de8652d1c70ba5785027bceeb8513dff18d4463476a2a819f493e66e2a92c, 0x053e864e5472e5962fa2e7e6d0f8473a8a19c7a136741ba85b4dc5098aac927d], degree_0: 2, degree_1: 4 } -point: (0x1e4703528a10e133cb501890ba07d24208a9e80d557fe6656098fbdb0ff6d074, 0x2a1f90c8f296f02d40d1c6840ab34865b22f948e991470f2accf5648c860e474) -f_x_b: [0x1d62683289b6dd5d750de86dde45fcbcccee1fd50545af71d569fad4c6f19861, 0x1ec0889bd1a69905675d0d7f1e46a9ccebb403149f06401dcc25495a11085d5c] -q_0_x_b: [0x1ec0889bd1a69905675d0d7f1e46a9ccebb403149f06401dcc25495a11085d5c, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x1e4703528a10e133cb501890ba07d24208a9e80d557fe6656098fbdb0ff6d074 0x2a1f90c8f296f02d40d1c6840ab34865b22f948e991470f2accf5648c860e474 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x2556b0eeccc865299a8eb34a72e40b538fca319c7eb00701b931291f1ad38889, 0x1f361a735bfdba3a230187b75f4d63a6860f944477ff9bebd12be0dee9b51ee6, 0x14cae644f7d8306f54145e074533df5f803244b5bb0b7008b9e69f467c123a17, 0x2c0d31f26758b90fb0008276f22d2b73a25ea0ab291906ae63854c9ea6affb03, 0x069665e6ddad58178aa9a8c9767a742b5896589f862ce1d6c73ea3bea3325b8b, 0x080cb3ac3afbbb5a33ff4447fddc0c66610afa494080bc2a9946bcb7e42de2b2, 0x1bc08e760c77292cd2587c433dbabf9314c39bb0777ea7314353514fcfcbef43, 0x11802ed77cecfbc35e142e1193cef3099a8cf2605352c6f50634950706679ad4], degree_0: 2, degree_1: 4 } -point: (0x2308143aeeb22f2825d94be2f10b7f33d6e04c491463dc8e0730d0fb0e90d716, 0x1eb5defff77731546059fc980a757ae3541ec52719d8e60003e3eae134e441ed) -f_x_b: [0x04f336a9837427a936781aa06591ee2ea3c36b3874d361fdd7788a78d707eaa4, 0x220a3757113ef0f19b94f7d1e48114f6081f3e83d35d52cdee88061889bfdc62] -q_0_x_b: [0x220a3757113ef0f19b94f7d1e48114f6081f3e83d35d52cdee88061889bfdc62, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x2308143aeeb22f2825d94be2f10b7f33d6e04c491463dc8e0730d0fb0e90d716 0x1eb5defff77731546059fc980a757ae3541ec52719d8e60003e3eae134e441ed -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x00ca9d4b100fcda63cd87ca2069cc82c1efbe6a99dbb24c0b89ad1a4e557cd01, 0x04edd151f98c7747e883c3298a6f5a5304d01c46c62645b161f10f77735a08de, 0x207601dd751d317d63b41af27fdce89d1a4caf730e5c5da8bf1e5e7fde409357, 0x19d1d5700a32a0af51eb3156bdeeaa0534491c55ecb7ddb96f2d4a6846c1266b, 0x0ee89ae37cae337dc15ac5c93b3655990fbdd9fd0201e50c551c4074ddcf0a75, 0x01cfe0e7deff5ee54edecbea25a2152d78e2aeb053be5ea37e90fe87f9fed8c3, 0x114ad7c4f05d45639bc644f21f9d4f6624c52b32044e1bccc7e7e7b49547712a, 0x17f2af8cfed28389e13fac4c49a027898147673e38eace631220085f556009e7], degree_0: 2, degree_1: 4 } -point: (0x0f11d3931b653f6c66128ae784736109c7373f3df832e1c3e73a15eba16055da, 0x11eee38223b9f99e99158decaf3b24cec7fb57f7d806eb06035db22e2d254319) -f_x_b: [0x17c1db658dcad482d2f2c3cdddd9f07a4c32fbb8225a81ea4fb24a7a2f767dcd, 0x28215ad67c1d13a948cd7a892fcab74986d137039533e3931b3f05c1e8a43624] -q_0_x_b: [0x28215ad67c1d13a948cd7a892fcab74986d137039533e3931b3f05c1e8a43624, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x0f11d3931b653f6c66128ae784736109c7373f3df832e1c3e73a15eba16055da 0x11eee38223b9f99e99158decaf3b24cec7fb57f7d806eb06035db22e2d254319 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x274b5c5ae0a18408778083c325dd9291159071f10897c228513eab99f7d98e91, 0x1c0d35642cdd2c4a520b9ed88e8ae9289ceacdf3ff027d5c1a5908fae1bbe852, 0x0a8895c9245e7c725cbe6c955ff326183e64580f90d12bc2af801b10047671b4, 0x0cceff273af9a33d033024397e6a1e9745724dc2d7dae312551c5b4232cb06cd, 0x006661689df5f62bcb77f041a3547c09c1bd444c884e8d2d4d99245be03aa115, 0x07b014aca6ebbe51de44802833676c6ebb437db5e376452121ea213f35280f62, 0x199a7f0f90e5e5e1b4c20a207f6170e893c1e051950bf0f01159fcb269a87410, 0x1a90d9111e06f891983de59340378ea50d8a0299c689604d2dd74bd008c3d669], degree_0: 2, degree_1: 4 } -point: (0x250bfb67497dbab64e369a24361867cd1caaebb71006924733dc99fc4a5ce358, 0x24424ad46eea5b4f8ec8fcaecd2c137fd8c330a5795d2444a59b36ff4cabe4aa) -f_x_b: [0x13443e7de07239ed258f3f221f9409893d89f14e0777c5b62f744af9a0dcb71b, 0x17184ba7ac6ed3a3af7b93c90e261f0e832cd06ea67184d5dc595b532798f2ba] -q_0_x_b: [0x17184ba7ac6ed3a3af7b93c90e261f0e832cd06ea67184d5dc595b532798f2ba, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x250bfb67497dbab64e369a24361867cd1caaebb71006924733dc99fc4a5ce358 0x24424ad46eea5b4f8ec8fcaecd2c137fd8c330a5795d2444a59b36ff4cabe4aa -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x0950f093dc46787af2217ca9eb7e8b4069cbc9ca454f4dc2d189b4e259d94efb, 0x013a271da447a23c051049bec87ac532117a3c6e149057147312634b1b760027, 0x13e59d6279ac1c99ffc4f1c98be9a741af3a4902516596895d4cab834fcf73f0, 0x0c9193d2af54ed5e86a41d13cb174c2ddc7d8ce3a21e02be5abe7733f69c8c5d, 0x254269acdc1f6d4b2c40d645a29f975aa0b01b1943ed6a6e590dff350dbedb35, 0x062582f8de010472c695f2e275830f93680754e7b94c3340be2652cca2904d52, 0x180d5116c82553c6412c339e2dc625a79ea8d77406f6bc0267b99da21ab4ed78, 0x08964f38e3655651a1b71c28c5de8e7f8b64b7a722c5641c15c57ed409e1ed59], degree_0: 2, degree_1: 4 } -point: (0x1df73cce693cfde00d368e0cbc48bd35dd0ea74cce9c795baa25a84344ec224e, 0x01c620bd078515ad665ee22c6f4fb96e3280c795ab18bf29a89b0222e299f700) -f_x_b: [0x1f72a0ef1e224931c673ca148ef0ecd10138532c3566c9276d0a6af8c6129459, 0x06f446314716ffc7eb5686469c51e859d46498e8cb1a1572108aa719eaa96eb0] -q_0_x_b: [0x06f446314716ffc7eb5686469c51e859d46498e8cb1a1572108aa719eaa96eb0, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x1df73cce693cfde00d368e0cbc48bd35dd0ea74cce9c795baa25a84344ec224e 0x01c620bd078515ad665ee22c6f4fb96e3280c795ab18bf29a89b0222e299f700 -here2 -res: true -m: 8, n: 2 -omega 0: 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000 -omega 1: 0x2b337de1c8c14f22ec9b9e2f96afef3652627366f8170a0a948dad4ac1bd5e80 -n: 2 -m: 8 -start to compute the scalars -f_x_b_scalars: [0x00000000000000000000000000000000000000000000000000000000002bfb60, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efe2adc1] -lagrange scalars: [0x0000000000000000000000000000000000000000000000000000000000057f6c, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effc55b9, 0x1920ea37b9b4f882548d5327a080c198d87ce2851642edb0922feb13c551cb48, 0x1fa3b24dbab8fa7d7ff20e46c12b81f7428b5145158cd21b8d1758dc171ecdd1, 0x30644e72e12e61f8baa5a7b06413e4eeef17e5640fddec5d77c419716894c189, 0x0000000000022975fe71beaebe48f79ed0bd5742f13d02cd32be92c1af9cd450, 0x196383fe528d370a43a3f0d91e68a9665deb015f265b3d701b80a032e743e0c5, 0x1f774bc954d37b7835e2fa7b17e63cc39441e75e6027479bdc36e01cab2814d3, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effbe070, 0x000000000000000000000000000000000000000000000000000000000002bfb6, 0x1743643b277bb5b7617516c8c7ccde6d3211c37b4806270fd73265f3a72231d9, 0x10c09c25267946f6e4921f492678514aa416c3337677865648750a6adb3e8970, 0x0000000000033e30fdaa9e061d6d736e391c02e469db8433cc1ddc228769ecb0, 0x30644e72e12f76b3b9de8707c33860be57769105887c6dc4112362d240640ce1, 0x1700ca748ea55b0f76fa30a37c4c674de7ee29316ece8ef202e0f9ed8c48140c, 0x10ed02a98c5d8366d63963620378a0b4d583d4ba07474114d600a7c4427a9d4e] -start to compute the affine bases -start to compute the lagrange bases -lagrange scalars: [0x0000000000000000000000000000000000000000000000000000000000057f6c, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effc55b9, 0x1920ea37b9b4f882548d5327a080c198d87ce2851642edb0922feb13c551cb48, 0x1fa3b24dbab8fa7d7ff20e46c12b81f7428b5145158cd21b8d1758dc171ecdd1, 0x30644e72e12e61f8baa5a7b06413e4eeef17e5640fddec5d77c419716894c189, 0x0000000000022975fe71beaebe48f79ed0bd5742f13d02cd32be92c1af9cd450, 0x196383fe528d370a43a3f0d91e68a9665deb015f265b3d701b80a032e743e0c5, 0x1f774bc954d37b7835e2fa7b17e63cc39441e75e6027479bdc36e01cab2814d3, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effbe070, 0x000000000000000000000000000000000000000000000000000000000002bfb6, 0x1743643b277bb5b7617516c8c7ccde6d3211c37b4806270fd73265f3a72231d9, 0x10c09c25267946f6e4921f492678514aa416c3337677865648750a6adb3e8970, 0x0000000000033e30fdaa9e061d6d736e391c02e469db8433cc1ddc228769ecb0, 0x30644e72e12f76b3b9de8707c33860be57769105887c6dc4112362d240640ce1, 0x1700ca748ea55b0f76fa30a37c4c674de7ee29316ece8ef202e0f9ed8c48140c, 0x10ed02a98c5d8366d63963620378a0b4d583d4ba07474114d600a7c4427a9d4e] -finished commit -poly: BivariatePolynomial { coefficients: [0x18d47523833d628dc9516d2c3f2aa4a854c6819df8c81de344fca22c2d6d6a5a, 0x235093d933c2dc8e006442e40f59356584badbb0f80de985f3c2b42e63d4a3bb, 0x1b0d9e6bf24390b3485e63a706b31ed9a215fe290a614a27973922d51d54be65, 0x2c5a88f1fa81fd750ff986fa942a991fac37309277dff1bf0867f78f4398b9ef, 0x16e9ec8eca5d95526d43b0d54f033c03eebda150e0309ddf561de32b7dcecb15, 0x0ae93f600f7ed9367026cde57271e8cda342984e5233aa48381cc7fbdaf544d1, 0x001c65234ef26383d61a187d9d3ab3d633bc2aca15d69a7f5a38a6c264bc4b4a, 0x0358044477982b2335d2a93691c7e9eb2badb080603f17892fd80e906aa39e5a, 0x2d90bf41bc98ab9bc375fd7a5e1999752bfdd5fea2242e266fac3f682c119561, 0x276067fadcf23d0534c2bb548db91b13520ce49b36f073c33fc6a1f617d65c5d, 0x2c1bd47e6a7cbcaabc1fd1daf00241ef4d2834c02475b5bb1a51ba7ffc9e0606, 0x14ad94d69be972d7a8c03657554c3833107eaec022c0cd5a9b846ca05b4c68e8, 0x1d14a51b708d1573ec8cbf1a4e49ce84427b4e5a1ff5e087a714b7966ea0a114, 0x2d3e630fae3965515cd8dd1df08398169e02c94bffd5d689b2d6a1ce8a2e52d0, 0x28ca801066c9faf4b8016d5ba272d2c1033bc308fa97b94e2fe0bf67a4cabd02, 0x1f13b984d6338636462ca261d19fb0f0bd10ef770cda524519338f10765c7225], degree_0: 2, degree_1: 8 } -point: (0x19caf607494c4cec1a0c345658db3abd2c9f095336723709d9817549be1a36b6, 0x1455c594e42ea77dfc669b0591a2aa681b14642cb7109fd9d5ca711de21c3c00) -f_x_b: [0x1b140a2a80f96c77e348a782b41dd22ba2422bea833e236da391f3ca21db3540, 0x2e86a768dc7034be81dc0e42a6ac7d345d8abd145366f1a0f3a40cc96d83a214] -q_0_x_b: [0x2e86a768dc7034be81dc0e42a6ac7d345d8abd145366f1a0f3a40cc96d83a214, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x19caf607494c4cec1a0c345658db3abd2c9f095336723709d9817549be1a36b6 0x1455c594e42ea77dfc669b0591a2aa681b14642cb7109fd9d5ca711de21c3c00 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x06aaa66cd5b474208cd92424e78e41ce4c035c351cbff64e92630f81205aefa1, 0x25fe7fd17d8444fbe25cb4eb3f6f21b7e210de17c1a81d3e00afa8af9fc98535, 0x1bae1ba8c74c85713eb765b2073ac273f9bd877993f12f99430b02dc40e5e7e9, 0x1a02d6cac12d25c073ddc1c5f9328b2dc5a5658c7fc0dc9d1207c5998b98fda5, 0x03de86fdcb3fc135988e5e553f58b574cce5b84cf28ef9bd682ea2493f0b1920, 0x262090c3ad1052494f77a629145ce29e6396838bc562e738e8b62e0b7601f537, 0x0e33e288388efaec51a2d2043adebf683c33ffb673fe9c9e9c0e9f8806d92b17, 0x0bba7f59c778f13c47060fed17c30dc79558815c00ef43d2d8f8bc23ee192495, 0x059cf4141ed6afaff488856ad23ef02e160d9597a10859a79afe52d000061936, 0x2276565ce7ad7370171ccc9223b17b592d5286ec48e65162f497524e09215a5b, 0x1b36095f59f776168b8a960b60adb436dec4971ee09beb87dcd4f37a4d4da300, 0x10e1245b8bb4d6243d17e43a17e4882261e76f3f5ba68d72814f3297d0d1a3ee, 0x27941cdd90a91c6f90a8da56eb780a7f217bd0d7ef83eb5ea50c5fc3466663c6, 0x12a6193f334fe44ee97e8854cb2fe97d89fd3a849a56d7410474838edf17337c, 0x0e4b71b55f20b8f96cd38edf4d06458788067cc76a7f64594b5ea860c628e772, 0x09f765bf571693b714dd37321f6c26f7d519d2a37f9aa9e540803896b1990092], degree_0: 2, degree_1: 8 } -point: (0x1ec01644b9bbcef2055130a01fa4479b32d78a6b7005714ede86aad3dfe96050, 0x302282feefc69b5efe00672f8e819a14549f2def850356737a66fd80953d7fcc) -f_x_b: [0x28b3edb320840173b7459ebf3ac0b0ae17a0b1ab3e2933dc63c0543cefc0dbd4, 0x29f50d3e3d81b8ef7d3c108d3f915ca9cbd44dcd9fe14d958a953659dba6b728] -q_0_x_b: [0x29f50d3e3d81b8ef7d3c108d3f915ca9cbd44dcd9fe14d958a953659dba6b728, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x1ec01644b9bbcef2055130a01fa4479b32d78a6b7005714ede86aad3dfe96050 0x302282feefc69b5efe00672f8e819a14549f2def850356737a66fd80953d7fcc -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x088cc2c738fd710509a3e942fa3d9e9405b58b33398aea6a009387a58aa71d02, 0x05717bb7ba85afaf1c465089e3a56ce8da898839e381aa719704e97095b05345, 0x1c01a1d13b2b38c56231055a8da499b9eb9f1306d71caa2c88fef22f9914808c, 0x012da239cea90d94d7f1c1f2ba54b728518623fdea7784cbc08ec6c66b04212d, 0x197083e0da56b18dd10de83540be07405fc98d4ddfe7ca5be477beb79d0a5576, 0x17b6a0c54871d0c2ed9b83106b05856f9bb9a5a46af7e37294e5de124cfb0a20, 0x1bcec07e7379b1dcb4597118727d2902e7b6de9e864b8bb5603a24a54d971d86, 0x26602dbb3b62881d15bc342b51f688a311d069e8af33faa89d0171b81c1f6d6e, 0x180f812608586de7231874ef49eb108b867b72188c35f096e033a4d608ea3c37, 0x10665f6baa32723907837a20b1fe6bad9adb0765b80247ffa9057b5c54d3243f, 0x13e40cbc3276600afe69903d0445028d9c94cc56d40b7657674d1a5325adfb3c, 0x07c675bb765b9d3eb0181c84f187d34c78be5441c91542039b72c3af13ea98c5, 0x003d4a61f4704b5081126ed8ce7eb6982adf7c53b3a869b3bb362067f49f6d6f, 0x05a88c264b3741e263ccd2eba329532fe656f9648f902cf44b8f36adc0c00650, 0x0b44a033c5836b300dc7de37ace6f6589fd193031841a75346b95b379b772019, 0x24feebbe276b950a9f17dd6b73a29944eb6e0a8ca07b1ae967d220a3c45c93fe], degree_0: 2, degree_1: 8 } -point: (0x2387996cef8dcaadbdbe95b0dfc2f962b85ee81a140b88ce0003882c8d6e664f, 0x07c495765b41d5c703a603f23469e8c2539457e8e2da404d11273bdd3ed166c6) -f_x_b: [0x2b5b2a31eb4c6e94cb94e8ca5540a178b303746ca343d2f388528a88751e839b, 0x0ae6a09d8bbc72b60370ad0e306b56ea101ff77b7e42923ac06e7a7ad59b9b8c] -q_0_x_b: [0x0ae6a09d8bbc72b60370ad0e306b56ea101ff77b7e42923ac06e7a7ad59b9b8c, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x2387996cef8dcaadbdbe95b0dfc2f962b85ee81a140b88ce0003882c8d6e664f 0x07c495765b41d5c703a603f23469e8c2539457e8e2da404d11273bdd3ed166c6 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x178622bdcfac2ac1b70274667410249f6c95090f6dc7f0f1cc23bf832503a5a1, 0x0c168b7e0630ffb46f845b035a8e91c45f9adde0cb16d0fcbaa2ce580476736b, 0x0fb16e9fe86f1f0cbc5db0ad2837715e3ec8784b74143bb2daeda2ecf8e4ccdc, 0x0f22f3f390015945f70eb842e539586a5312470535eb3d43539bf0e22f92b4eb, 0x017b66057a57dd67f327b122a03506a7c4140e3754f3c3b1fcbbc4584296a7ac, 0x18dbfdbedf3d77211ae7c0a8f18d49bd2eecdbeab23a43c48907a04f1d8db5e6, 0x29e3b3e61f519759464b11045ae762ff7323a1fc2066b462bee7fcc1e235bb00, 0x2ff020461fb45d8129f5a0b3aad4b7c3ca39de762ed421ec9fe83deedcf14a94, 0x23768d455e391198c42d9def71bafec187758fa27769d446ee5d282de3ffa877, 0x09292d4ff8cd19b9cd76440ec0d13cb75fc11d5723ec63a19d2d0e5de174b0ea, 0x29588a6b27d8a8c7574bdfeb0dc4119095cfb4ccaff6357f6ba2189e51048d22, 0x2c4d6db044dca22823521f3a76b29d011feb7003e543b27d45bb4134b3188237, 0x000fb227a29871dc496443997aac1d2263f3766bb8ef61abc8593f47a45e91f7, 0x12e90d5f2e376d94f508b86c9b90406b9af6ccd23f6ad2dff1caf338a4e8a8e7, 0x19535c3329dda1249b81e8afb4a72b4299cf75a2b312914bb09e68ae65bdc708, 0x191d104f896ba357e784c76058fbc25c2f40a54a226d1b3315f573876a8a47bd], degree_0: 2, degree_1: 8 } -point: (0x126c99fe6f9739e915f24b64273d9fe9d6e8f9ae4b9fa94d7c003b64f80c9c78, 0x129bca3110d145fa78a1ca07ab31ae38deee84b96e8a3a31148cf1c090369820) -f_x_b: [0x2b25b8bce3d11a7dea59456489cf240f734f8dd02fb29148542e285abb5c047f, 0x10b1f1452bfd996fc7424dcec3a84a92cb390a7589a66663643679202ba8a235] -q_0_x_b: [0x10b1f1452bfd996fc7424dcec3a84a92cb390a7589a66663643679202ba8a235, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x126c99fe6f9739e915f24b64273d9fe9d6e8f9ae4b9fa94d7c003b64f80c9c78 0x129bca3110d145fa78a1ca07ab31ae38deee84b96e8a3a31148cf1c090369820 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x2797b6752243bcd852a26e3f2ab951ba1a557ed20ec7a47948d263983fa2894d, 0x20f6c9ed83f294fcf80e7dd9922fa64b4d13107f92c2e7b3d0cc83a614eeb143, 0x0665711b67fd014f5c9e7934100c1d83b81689d849255b87635a990b39648188, 0x0df37ddc1ba4aa5ba4b46f061ffa7670cfbf926e16779dccfa1986e15be55f5c, 0x2dd4e9d6aa8c13fe2ce29b74bd8baec0b3c1bb50e9b0b5ac35581a7dfc6d15fa, 0x1bc825916bbe9e5a9b9150abceb6a919337ca7ff96744d596f88459280b1582b, 0x20889f9d9e9bf3e911bf2d33acfd8e49222f867a80ebe4ded7106674feb0a5b1, 0x072f799be18040b272156bee3fdae5325eab7357d27cab466efc3034a37d6985, 0x2d1a103d60345de5d624c01c4bbfb600ca0129b7ac7ca4b4e48802d9b40533e9, 0x0d91a0eaf153078c2d2c053f1bb603070ca969110f4981b8410698039eee4801, 0x08cb23061c36bb93c733545ad02bb42799ef63b581d58ab0d128542d509b875f, 0x1d80fb901fc0a63359920ddb6f8a7e23bec52419c7de64d5326eb5df5bc8b344, 0x25f6e28e3a53848ab4e0eaf9938ae9ac7d25c31725dc1bc0ef9ddb0da3883e02, 0x0b938564d95c0bbf7bbe5ae79b54342716938a91f73450b908c28dfc991c3f12, 0x0fc0bdf29a013f3df99e7fa930013a8e38037c2e657f22b52f62e08f85213118, 0x0ef974a4cc43b8bd3f36f8325dc467f8a2ffaba96a0ff7afe647f6fd079f1519], degree_0: 2, degree_1: 8 } -point: (0x03e6bfee76c11dc1dc75f414008d2590ce5519b65d1f52851af5add70be58ab2, 0x05eae05ce1ebc06a036d7f0b720a437b89b01624752305c3f96d6d9d7abd50f1) -f_x_b: [0x270569fb60db3de0e68aab5f8c1ff19536d85c5042fe88afdb81907b9c2645cd, 0x056fcb31036c05b079e788de7cf87efab57894502084b7de5ecea3034202b0c7] -q_0_x_b: [0x056fcb31036c05b079e788de7cf87efab57894502084b7de5ecea3034202b0c7, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x03e6bfee76c11dc1dc75f414008d2590ce5519b65d1f52851af5add70be58ab2 0x05eae05ce1ebc06a036d7f0b720a437b89b01624752305c3f96d6d9d7abd50f1 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x104cc03d410e205b3efad8fa02076b4ab102b28320e7df92490fb77bc534f683, 0x20fc315086b230d4070ccea9f54350b93af438ca8c11dfd220ad9f5bebf3643b, 0x09faa8c2f3a60e9621fef56327e8b6a85efd33172f8484b011bf661222f2c0ab, 0x232015624077597123a11b9bbd5c626dd9e05532496b433b7f2715f5b124a24f, 0x27fe6195f0202f0e988579de9d35e4c628deda71822a0b7601b3c9b2aa8e4fd6, 0x28ea595b3c68fbb88d99a084a8dc5f495f36d94d62a7360b6d05784f9cd4e61a, 0x00620b72c083f7b5cb4d348d1532082ed93b98ebcd3f424d9dd666e9d991a847, 0x21f213e7dcb5be19381f4a7e0a7c3392322e0112220c82d648603c7d62854643, 0x1f9e9af8c5df97951a28396f862b9a2e0fc476774470a08cc57f899b4fb96e4a, 0x1e9bba373e3bb18e2968fa1e7f6e30d2bc84b73e0b8767c48e2beb920e007885, 0x1a5ba0e9c0292c75f19a13eaa4f30f64963d985eee335cb97b145af25e27a951, 0x0500a3f3af2f8aff7dfa03a839c168e9522a95d062da9502386df73d48f03c95, 0x0b6557387af4495e17016b63a4cc272e56591add7f6274fddeb1463ccf50618a, 0x06617ddc3fde8e2eb072b296abf73a9658a4edbf7ad573fe1dead18e0fecdd80, 0x2a84069b8c302cc45558d02086dd8b157f096ffc2c3be7eea7a83351536536f3, 0x07ba9e79ce4f09bbc38a5bc9c81e6f7ac81927878e41825aa03a0232fe688637], degree_0: 2, degree_1: 8 } -point: (0x02e87b2a7477a3dfe9e43a97c3803e3ab98e0828875ceb4337abaf43c5707fe6, 0x2640faf037b931a2c29dffa7fbc15c9a764b62dacbabb10904d229b80e797ab0) -f_x_b: [0x1d32e4c3bc1d8370cad34e73082928c66fc97608c21fb5aa06a7a87ac794635d, 0x165cebbcc2825777d82cce88cfcc0ace9160415d60d4f5653788ca58a0ec3b14] -q_0_x_b: [0x165cebbcc2825777d82cce88cfcc0ace9160415d60d4f5653788ca58a0ec3b14, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x02e87b2a7477a3dfe9e43a97c3803e3ab98e0828875ceb4337abaf43c5707fe6 0x2640faf037b931a2c29dffa7fbc15c9a764b62dacbabb10904d229b80e797ab0 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x277092dd21407b24088a0f71afcfa3ae97f4bbfc196575c321876ed7afbfcf8b, 0x01fdbfddc7724b39dafb53d5616e6e6570af89051c9467afb6ce2dcc683e20fb, 0x0679dd03450e449c675b4ed6cf2cfbe8a240a02c4912343f8145609757004544, 0x2d5463bf2053a16e2b228b9cbd7731754a2213a0a79927bd8eb3d592e75916ec, 0x19ce09a20644cd719f0f7097e87fae7b089a4ef0bfaf015d4281cb7bf376b5f7, 0x0b36fc3e6335ef870924cc8116a349f36a36b4c0dab4565e14559acb1a5e555a, 0x2c53987e7a8147b7bd17ce8c0c26015ca9eebc559e93f8002c16999cf987a3c8, 0x060203761fef2838f2dcb99487af27b1377f5edf18888a0f7e6bba57ddaeb590, 0x1638774fce85cdd5c857a59081fffc2dfb65156111558c5d5802044f7d8d2e46, 0x26de30107e8e5ad9ed73aa589394559e321c72df1adabd2dcf7fab169e8b1eda, 0x05a6b47cd0a2cebd118bebfa6622ec15fc1514a052fae2d497dd998767fad565, 0x2eaeb72f4962ba66062a317b53a4b579423214041b2c73db9696b3866a2c8eae, 0x034f41db3ff78d1b302d84bfe462b3c419c52e55bfbcce0284f9e24a7f03d71a, 0x26a65da9f1cfc59414d56bd0f0bfb89d02bf4973e35e48767b16390411b0bb05, 0x15491db551169deb7a6a94200d627bffb07a29bdf8be7b45b480038be4578723, 0x19d05a1c6b9ce55b16ab990160438705471261bd2a75a15822ca38a7c15d51e3], degree_0: 2, degree_1: 8 } -point: (0x16ccb2481b82213a69d346c1620ece644c2d1b4ff9498c07327ed57da9e6df82, 0x22866fc7d2426f4a33c1a4f9cae665fc84bc76ca462a2971ffd9844597b1b951) -f_x_b: [0x2a2dec881f83252c8349ff66d2edf1b588be80405814f958994f96668d290724, 0x1f0c076c36e77ebabbd3975263dc9c3f5469589f94ba69bbda7a2ae129636fb2] -q_0_x_b: [0x1f0c076c36e77ebabbd3975263dc9c3f5469589f94ba69bbda7a2ae129636fb2, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x16ccb2481b82213a69d346c1620ece644c2d1b4ff9498c07327ed57da9e6df82 0x22866fc7d2426f4a33c1a4f9cae665fc84bc76ca462a2971ffd9844597b1b951 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x0f8b13634581a3f0a4fd366a81cb8437a011f97015dcaeed7633af77446702b6, 0x17c362271d52cc4522f0d15344ff8adfc1cc1d9f9cca02da4f77826bdef77b85, 0x0d53326246744353ce43ea7e4843afe9939fc4e7d4c9f7420616f341ef87aef6, 0x21b8e001e2cf87e373fd5c889edfbca67327696f69b7f3f6bbb1edbeade5f572, 0x290293fb7461a667803c035025965bdc79a499ad155cdbf4481aeb3d044fd7fd, 0x0832cc4f94d2e06fae044d31635ca404ac4d3ffc5ea2e301df8a7c90d64fa40b, 0x257c648132d3d9ee5ed1add9b95dda5ef104be7d8d35b12eb70d57ce6325e064, 0x125b1935ed11e4f6ca22d18d327751c9317c5f7a1b2ff32c8a034ec1b7c03cc3, 0x11aa8bf718ce7c96953a33fa827369f902c1b62695f162f97d71e57266242e18, 0x21e4743e1e3f4b833de505e57688a598062774bca65bdcbf4fd86c206a3cddcf, 0x02749526e1c5abd50762756a07f076e73b16793a9effce94c30d4e66bc8114e9, 0x06cb062f389422a549cf8ee326fe2106786ba3bdf8391b0b78af12234283eb6a, 0x2bb08d9d902e1ff2db941861ff205762688fd84f94c47fcd0131c7d123f8b310, 0x23c1b59bfb2855df94ed55aea082ea6ea22d6466658a350655e1947dcba60e94, 0x088a81ab2a7b5bf8bee3d70b910b11ce553043e4899018abd943c7bb90eb32d9, 0x1dbd803e16ade422a902ae3904416fe27406caca70fe86beeb0ac66332d33a8b], degree_0: 2, degree_1: 8 } -point: (0x137f2aba275cc034d8f23e1d50e8cd27f694fd0f996c2b84b67663ed5da68be9, 0x2d0fc92a7b06c46f126d0a03a13a760c8bc2f27602e5734c5923fcc36f0cd8f6) -f_x_b: [0x24766d75fdac7321a84aa118f453f65bf94433d3dd1ca49626459a9f36492b38, 0x091bc023ae26ded9cba47a3408c09c2a7e19c6e8d2a19cd950881119d84d7f4a] -q_0_x_b: [0x091bc023ae26ded9cba47a3408c09c2a7e19c6e8d2a19cd950881119d84d7f4a, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x137f2aba275cc034d8f23e1d50e8cd27f694fd0f996c2b84b67663ed5da68be9 0x2d0fc92a7b06c46f126d0a03a13a760c8bc2f27602e5734c5923fcc36f0cd8f6 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x09bf9497ada87876a8b185e9fe3eff574b2bc4e86deb4d5b63d05b3f2c116471, 0x23acab3bebcb1574a5783791e026264a4955d798c8133eda9b0d6df5d2f9b492, 0x27bd9c719a5a5a005e940b40cfc3ca2e3c1f8dd7269d1cdc5c46141585e90880, 0x0fa3855af6e71f81e482dc94bbed91dbbd42040633531a35d815a83a5fbc1482, 0x2e5e511f508358526e0cfa4ab2bec58505d07fe8b4cbff84965b58be046aca7a, 0x150b30e62887595fff78e50d7e6c44f5f6ac64b4495ed7d7edf37eb42cb7ca62, 0x1f20a556b17cc3046c7b43b2fded1f78a6fe1147d8544b105e85aef6094b1b87, 0x1a65c86b5850e75594eaee5a8a9f828c3c1815ee88d91c1e6232a1350dcb355b, 0x20b859b24eb956f4e92e006b02d209d527467e652e913af78be2a539ed4afbba, 0x303c115941301c2eb3ea1a5d022d1906d830d17bd02d59cb9c05d6b3b304c6bb, 0x18f1c433bece68b5932dde86a551994834a59710986ae90a4cc17b11b2724f09, 0x0e8cc22d4cae37bc62afb16526533dcf2deb306ae5a52fbd1eeef9bfd84767a5, 0x28b69da0d96e5c343ebeffe163e9e09f650f4d17fd2b458eb40ae84e4a3440cb, 0x0bc2c3f897215db354907dfdde931b30146bae41539f3a39b8788361ebe8a9d8, 0x1b73a5c5cccd4f86eeea821279becf0d872b12e00d3570ef5ce47129c64b15ac, 0x1222f92e6bbbf4104fda13ac6f90934c694fea761ad933b5aca2dc4532a32e9f], degree_0: 2, degree_1: 8 } -point: (0x11d5a897309a439ca0fb9bbecd977302870542962f3ebe370e370845cb2ed6e6, 0x21836fd5bbf02f1ceb168b8b1eead1b2defff6ae6125f383066f279d9c086c6d) -f_x_b: [0x19fc83c93663decb7e5f6e823d80a1ac1fb151cf1a634e1b546a42550f61a6c2, 0x142b96895d093d45c4fa24c06e704061969a372b850cf07720eea103dc75c025] -q_0_x_b: [0x142b96895d093d45c4fa24c06e704061969a372b850cf07720eea103dc75c025, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x11d5a897309a439ca0fb9bbecd977302870542962f3ebe370e370845cb2ed6e6 0x21836fd5bbf02f1ceb168b8b1eead1b2defff6ae6125f383066f279d9c086c6d -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x1c3ac34e6e356df8d86fefd82c242bb8e1fdff7cca033da959efa395fec39c75, 0x18a4f6fd166076e474cdf28f0177dceaef65e081c28d55d3dd0a235d6d02df34, 0x03f209df2a96005111af53a63570c35217b9a8e059b1275506fc29efe0c1b287, 0x2c0f3d96fcc68b512ce64745756f7af37f3a3983dafdef91ddd24b749408af49, 0x2dbf898f0b2b758464f0f6cf1484e3aeb5d098b0af8403ad96e9c3204cfdc5ed, 0x1731cc61a5b877f4ea2679acb44b0371e673e07556283151eea56ce15c76d39c, 0x0b51b67ec633db0a66d42e3ec8fd18040887e5a1cdd903978841d4d448dcdbc8, 0x1a5a379470047573ba8a70ed7a65adccd87572dea876fcf3f28d2d6f3ba39c38, 0x00794b9ca415f758778541986b7f9c5199b50b108e52f3263f2a1348038da9ed, 0x2ff3c93c77a9fa53a6e4277d22743e54bb5206360e34d52948066fca6f8f5c26, 0x09fd80c0ba3e9666abcb7cd6e88bd20864fb55b7634c3fb5e50ed610c6327bc9, 0x10477aeade0ce8e6d9d5a2874bf75557eefa64727469ff20f84caa42b4136270, 0x068a6753c4ede3bdb9ede548ef62e1470d919afa3f1a1fc2973fe787a721e723, 0x29ba14e3599e0c5698874c72512431b363245df362df0b48bd3cca16a266c3f1, 0x2e0b5e4954fdcc1c27cba2bbde9da0c2b4581f9bd7812174f2c400d9dcc1edc3, 0x2b866cb266a04bb5ff16d2393123e4a7631c07c0cd6416f23db77fa2e6614ec6], degree_0: 2, degree_1: 8 } -point: (0x135510f3ac671467d0e0db1ef1917050aa419c9bc9e38c82e6e0150fe0fbfad3, 0x0164337fd23315ad2f606a12785066e209a0821d3357c05f9320a948822fecdd) -f_x_b: [0x1c0c3da5f0d8a10819224fd69c09e7018418e29cf63f79d4ae371fc0474d513b, 0x10a6fe7ea781e25daa6492573a878b23f1bebf90b2d6a27555b94db8c2da2fdc] -q_0_x_b: [0x10a6fe7ea781e25daa6492573a878b23f1bebf90b2d6a27555b94db8c2da2fdc, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x135510f3ac671467d0e0db1ef1917050aa419c9bc9e38c82e6e0150fe0fbfad3 0x0164337fd23315ad2f606a12785066e209a0821d3357c05f9320a948822fecdd -here2 -res: true -m: 16, n: 2 -omega 0: 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000 -omega 1: 0x21082ca216cbbf4e1c6e4f4594dd508c996dfbe1174efb98b11509c6e306460b -n: 2 -m: 16 -start to compute the scalars -f_x_b_scalars: [0x00000000000000000000000000000000000000000000000000000f1cd282bec0, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1eb80b8fe2b81] -lagrange scalars: [0x000000000000000000000000000000000000000000000000000000f1cd282bec, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f4f2bc8fe2b9, 0x0dd6169411fd6da4eaea98009b6353a6b09778009a9ed7b9419364e17692b261, 0x06e80b18e9bcec4aa0d3b1e718e8e5afed01a817c17e95b4eae90e9b00f38915, 0x15abf3a69855b2340a466d7350f927ac5f7a68b22144a4aeeebb83c92b4ec797, 0x11d03c8830929ea3c95be582205acb2085d0ffb9904ddd418e19a131d876259c, 0x03981d79ecbf8409d58b02ae3bf01e43353a73a0ff779bbe6518fe0873ab6be2, 0x0dbc067fad3b880759be1573588b0947949500577e43685c288ffdd6583862bf, 0x30644de43fc26b3ac6b37528a757f1e691631412ee3a46cbabeef2b4fbf5ac89, 0x0000005f164a2349f6688b093c1b99a4648b3823b254c683baa201e9f806e250, 0x2b66983d871c2ccf5bebc18c2d60c1e668521d455e8aa2123a554031969472aa, 0x0353cece3c0e4ce6e84302c6e2c0644f2a968757677489aa065dce4190f25e3a, 0x185d0245c482f69090498acb383720f48f10382754f1df5d7e873baf7f193e6c, 0x20264cef08da511ead7493d9b15c97ba1e29182e411830fd9a32787445ef2bb9, 0x0d819c7c88243fb902912ee7079f3a5657f4f308ea52bb7136242be6458cfb92, 0x07205c7df04db592910f4d4d7b6ba13ad2c356123706a88f9d333497cc4cad9f, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f4de9621df10, 0x00000000000000000000000000000000000000000000000000000078e69415f6, 0x16c6d525b08eb71edd59d69629bef4bd7c7c519cfd7a2dbd49fc5b3ca05ea33c, 0x213515af1627d0bfcf69b6a7bb020a897fe107352612a76867e4636b85163dd9, 0x1ab85aa2b7f98cae8dc81bcdf78ff2db6302137d5cc78813c0d93b0e2a32818a, 0x1e941206668b426004758882872161203b87db4a3bdf15d96dfbce352933a9a5, 0x1198eb78f349233ea5f3e902a8320f01f6cc7e6158ccfbc136f5fe131747372f, 0x148797514945a89cb6e83dcd3b8a30e77644f144c09da3355df2a500907b308c, 0x0000008ea16f34eef19cd08dda29667696d0d4358b7f29c597f302a4ebc33eb0, 0x30644e13cae77cdfc1e7baad4565beb8c3a8b024c764aa0d893ff3d0a82880e1, 0x10c518ecc63a42bcf4639ffb3bc9c243f5ee65d6bd0a2d91511c488085971cfb, 0x04f35eddc6e9b38fefd85740034f469c69725ede55370724e08dcc30f6f09759, 0x18074c56ad910ae0484877608242753dfedb1c3a2074d50259a7f09ea0e67465, 0x103e0168226b0e30f55a898eaa29ecbf70e5dd5ee62dbd09f17c034e34bbb268, 0x0db1a9052b85652b924ce66d6a75d4ed694b871476e729a8e2716fe9cbdf89fe, 0x07005422d8b79c9b8692284939873a2b71def35fd94e5f152a5507401d6af957] -start to compute the affine bases -start to compute the lagrange bases -lagrange scalars: [0x000000000000000000000000000000000000000000000000000000f1cd282bec, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f4f2bc8fe2b9, 0x0dd6169411fd6da4eaea98009b6353a6b09778009a9ed7b9419364e17692b261, 0x06e80b18e9bcec4aa0d3b1e718e8e5afed01a817c17e95b4eae90e9b00f38915, 0x15abf3a69855b2340a466d7350f927ac5f7a68b22144a4aeeebb83c92b4ec797, 0x11d03c8830929ea3c95be582205acb2085d0ffb9904ddd418e19a131d876259c, 0x03981d79ecbf8409d58b02ae3bf01e43353a73a0ff779bbe6518fe0873ab6be2, 0x0dbc067fad3b880759be1573588b0947949500577e43685c288ffdd6583862bf, 0x30644de43fc26b3ac6b37528a757f1e691631412ee3a46cbabeef2b4fbf5ac89, 0x0000005f164a2349f6688b093c1b99a4648b3823b254c683baa201e9f806e250, 0x2b66983d871c2ccf5bebc18c2d60c1e668521d455e8aa2123a554031969472aa, 0x0353cece3c0e4ce6e84302c6e2c0644f2a968757677489aa065dce4190f25e3a, 0x185d0245c482f69090498acb383720f48f10382754f1df5d7e873baf7f193e6c, 0x20264cef08da511ead7493d9b15c97ba1e29182e411830fd9a32787445ef2bb9, 0x0d819c7c88243fb902912ee7079f3a5657f4f308ea52bb7136242be6458cfb92, 0x07205c7df04db592910f4d4d7b6ba13ad2c356123706a88f9d333497cc4cad9f, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f4de9621df10, 0x00000000000000000000000000000000000000000000000000000078e69415f6, 0x16c6d525b08eb71edd59d69629bef4bd7c7c519cfd7a2dbd49fc5b3ca05ea33c, 0x213515af1627d0bfcf69b6a7bb020a897fe107352612a76867e4636b85163dd9, 0x1ab85aa2b7f98cae8dc81bcdf78ff2db6302137d5cc78813c0d93b0e2a32818a, 0x1e941206668b426004758882872161203b87db4a3bdf15d96dfbce352933a9a5, 0x1198eb78f349233ea5f3e902a8320f01f6cc7e6158ccfbc136f5fe131747372f, 0x148797514945a89cb6e83dcd3b8a30e77644f144c09da3355df2a500907b308c, 0x0000008ea16f34eef19cd08dda29667696d0d4358b7f29c597f302a4ebc33eb0, 0x30644e13cae77cdfc1e7baad4565beb8c3a8b024c764aa0d893ff3d0a82880e1, 0x10c518ecc63a42bcf4639ffb3bc9c243f5ee65d6bd0a2d91511c488085971cfb, 0x04f35eddc6e9b38fefd85740034f469c69725ede55370724e08dcc30f6f09759, 0x18074c56ad910ae0484877608242753dfedb1c3a2074d50259a7f09ea0e67465, 0x103e0168226b0e30f55a898eaa29ecbf70e5dd5ee62dbd09f17c034e34bbb268, 0x0db1a9052b85652b924ce66d6a75d4ed694b871476e729a8e2716fe9cbdf89fe, 0x07005422d8b79c9b8692284939873a2b71def35fd94e5f152a5507401d6af957] -finished commit -poly: BivariatePolynomial { coefficients: [0x2f8fff6d59c70b0bfbbfb9dbcc996f02d19a1cd349c5498ed15a07ba866cc7a5, 0x0ff73c7a989ce2b73a85ba7b6df61b18df2bb80cc316664fd110322885255f8a, 0x181c1a3488c645394f340ade7c0c65c9d3f5972057f1c394b66b54c8fd32efe4, 0x29ffb80d093ad0080cba341a8735ffd941ee85b1075e1aae697de12eff2c44f4, 0x15168bdb338a09f7909ad0bfd28b05aaec5da61b41cad9c13408307f9b75591a, 0x2ab2b6d18ffdc8a48d84876debbb4dee032156de05474d772b739e6dd0fc7537, 0x0e5cefbac28373be56857646d1bd0bffd4913b341cce2cc019ad31548d35b884, 0x1c516b4265715605ed81f0c5f9eeb57ef04a72d8e76ba424c0acd508b0b03e3e, 0x224b5e4fc7a8a75446b5d4665f9a2df004227921041130adf4b184eecb927d57, 0x15ecbd52b5d40b74c8a757cfeb93374699a09de7d1bb1f6ca941c7fe4e2007b3, 0x24c4ffb301f5c7d16adf08084e4bc893ee3cb8a363c98f482f31f355738d868c, 0x0ada4a52c423369b746a6eecceadae56e6fedde075df8e33c12219c69b2670dd, 0x20b0752074181e695a40a23a8b1ee0652e9d206ffc78ddcd86de678200ed6027, 0x1b029c29960d7d91347d51ad93b2494a8725fc87f78836cb60fc65b99463c401, 0x23abb0e65b460f8a1c941880b2f09ac8e04f23d90ba08080b8334f6d59cd0459, 0x00de4a9f939cc0b90d45ca867383f7e6d0632ad9bf0f9efa2f8059550ef3c4a4, 0x1ec24f80bacd9f3cc016e65f76abbeb53da61c88f66f5ab3bcdd38c22445415d, 0x2c49e76160448a1b9f2d0a34e280fafae94180ecbcf4e7be5e3afe97ba8c243e, 0x2d4cf48f69df660a011574074ad1f4de1b83527a9f7a2c0da80f1790cb30a48e, 0x2e915ae67ffb792eb33ab85cb498fb439a995c6750af1aba7f2d539f19777fb7, 0x0bc01c16b9ffbeede4890cbbe2d882e26cb9f4446c06d3c59cc81d5690f867ce, 0x160125cde189224184fd4642698b26b9892aaa730b7e74e16372eeed52cc3091, 0x0c8ce0204469fc4e9de0a8c4545a2b79224c98710bf35eb3a0937b67bab08e86, 0x2a89d660bd1a7d29a82c8ab08d7df7a68d04aaf1349b38869a0e658ed639aeda, 0x29070f526134ae57538ebd5977213ed56a5e91f7501737a5f5728440dce39a6f, 0x0decbe52ab128987b439e2618a1ed617881e21ef3627b630e4eefb4e27b8d892, 0x2c95cb20ce65dd0c2a887a41b072a73553db0815d291638d37bf22685a2a5ad9, 0x0a9710953dd682fa1d232054a396da77c437ec2e147593038d304334d1bf3cb9, 0x0ce1bec9069a36e8155d08e3009db1a89d50a65e6d66bd8e5333fedefab33ad1, 0x063dfcde59b49a54adb04d3f11fa5d7e3d7384debf1fc184c250115b1b683862, 0x0f9c9585a5c31adcfcaca8723217e1d0a735f0c3ea16ee19380e35e3b65962be, 0x0b827bd61259f8b6b05275af9f72912591375210ca7758d52cc97eb646259fb3], degree_0: 2, degree_1: 16 } -point: (0x12d2a857f7cf96964664bfa2ec9002170c770a638e55a1bc5ab4c4fbfd998b14, 0x01a690a47d2b2c084426f4c862e6f87f83de4f09db29ed650e298de52732eddd) -f_x_b: [0x257d83db820a72d2f756ccff56f530db0419b5eb0961c24ea64150abede80b3b, 0x0042ed2030fb1ce92d68e7dadf5b5dede823d64955d85bab8c46dfea0b5138e8] -q_0_x_b: [0x0042ed2030fb1ce92d68e7dadf5b5dede823d64955d85bab8c46dfea0b5138e8, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x12d2a857f7cf96964664bfa2ec9002170c770a638e55a1bc5ab4c4fbfd998b14 0x01a690a47d2b2c084426f4c862e6f87f83de4f09db29ed650e298de52732eddd -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x23ea8ded791ab1fb7772da9c34a381716793316a367f5d438f05322d5a0ff55b, 0x0e5c05610a83917d4ad0deb6aa919b4ad028423004567b5877da1b4cb0d7cc77, 0x13edb4d06737f7fa4ec30c3ad13c2695cf3a38498317051ee54ca21ab3c45baf, 0x2b66fd74310a6bd4c525dba9fcd78703c6be50301e8aa9ce57ce17a201806952, 0x1a92353bcce4211375d744347ecd7140e56cede94c917f1787748bbeb462407a, 0x0e70e5280ceaa029db172424887b29ddb1a599faad2808ec2ed1741a8c7a0301, 0x205bfe113f451d4215fc3bb9721e81c14f0b25a4dafb43aeccd15fd287c5c9b9, 0x08f1a456313718ba9b2c931c00422d89f7d6f26547d65904df99ff1872d16b19, 0x0e1f23f73b2d2761c70872b8df67ce6f8a680fc0f8c00f175e488483c61b5ac3, 0x2ae0f0df84c5337a1607fbf784ac01f3b0091bd4d7e2aacf65a809d6e83ef76c, 0x1048d6f6626cc5f8d99843bc3a0b8e5b5f95f3a43d25d841ca1f7934a779dacb, 0x221c41536e77d3cd757f0304f12ec2eed3a506f72c804a5fcb39f61cf2ad747a, 0x2de958098021c72e7dc25bb46907e9ef40eada30209e768e1485742bb5c103a7, 0x2f92c6fc7a4c52c3d6652f779c0b8d51fa0b5135d09c472081cb1ecade0bafcf, 0x0a2973696c9f24644de1551777e8f11d9d9be05ee466522fe1a52ed68186a8ca, 0x11154e7b09820cfdc9c7286f0bd8d9c178a76983157da84984aec9f0ae1018da, 0x079d7d90bd4739bca138dcd6f15a28ad8ae236664128400ae97de072eb5b8bf4, 0x29eb10c5becd6f41198c57b9fd69ce4c53ae3c8794904224927e8f2ca25cfdbc, 0x2e15c14395b306ca689d928915761666bf9d79cece08c5b2b383287dc1568412, 0x0ba181c48b08961ceff1857f030c7b36f49741e218f9797960e8836f544c413a, 0x2deb377f6795e9d56b8086205bf262d4d12c86b446a5e144086777b32326f491, 0x1491ab4f05a5a5d8802bae711c2407e52096a9ede07b703d505b112bc6ee1ec2, 0x21a101f858fd4408b82d5917c3c4377649102644a3bb1c5e4a6ae108bfb6c60f, 0x118083b6c8fb7a841c2277e80d9f477aa92580e37b45a17ab24b413bb5eb9ad8, 0x0b6f8405e57a4ef56caabdd8446117dc744816352f0c6329c284f08a96c92c9f, 0x2a247edd6b6562855897d0e313792bf5461a026de18e2f2dd2cd8ec1fbe0a707, 0x195b5487efbc654c0493e1c87da1eea402ef7a5feda27072766958ff3344c891, 0x0a33049ed7af4545684a3e363e89fe014219d5b23ef94ee92905aa25a7bb556f, 0x017784d9d1632414428d21a5e4bcb27346ebf48042d4c7c74a764760bc0cd8e5, 0x0406cd959dbdfc84465d4c01f59998e3a56b13f3ac57eb05f8b61a66a8edb213, 0x1304635dbfa302ba80ca831c5a2215b1a86f496f178119de1c50f2bbc07174f4, 0x251c973f3d063f2623ae973b7f01d6c903e4204d4c1aafde77ae507c06bc3f71], degree_0: 2, degree_1: 16 } -point: (0x0243f7911020086fe38f0a237ed025cf1e0ded876810d1bca1ffae066da7ac1c, 0x0c51455c53b6376600b59c93d7215ea690400c73489b35ba2d5b240a34648161) -f_x_b: [0x162135c807aaaa4625126c3c6a253494585a45eb62cec32f10fecbec4fa1bace, 0x2328ee45ab553fc05d3a10bef217bd74f8af4fd863056ab8ed673f201f57a1db] -q_0_x_b: [0x2328ee45ab553fc05d3a10bef217bd74f8af4fd863056ab8ed673f201f57a1db, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x0243f7911020086fe38f0a237ed025cf1e0ded876810d1bca1ffae066da7ac1c 0x0c51455c53b6376600b59c93d7215ea690400c73489b35ba2d5b240a34648161 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x00a40e3edc4b5b58aabdcd9b0133baa7434e13b2c673313fa839b820dc28f7cb, 0x075742e2f8fbff4811c1af15f1244dd61c2adeeb81687b8e9ef7d77ffb4faf70, 0x1fae6c73fa354031429759b010d064d217774e828bc7353eca545b22ba03aef4, 0x29665b858bee95b619d1678214b727b952af07a59af99716c1b61e3d623b339c, 0x0838a758c6da110fe12b696f78e64cb4d33e7b6f63e6882167d11c8647dbf422, 0x2475a0f6056030e36140cdb63376e74368c6662f2d94665db522fa89eb180c1f, 0x26f559516bee997e1eefd0837915f37ed9dc585cbe9244bce02b153c999bb8fc, 0x2c2a9f13ac9fb814d4ba60a2a16c9a8d318a969208dca6ac84c9b697f2a87cc9, 0x2feba57cb2099376f5e0a5c30b8651b6c29659960d804dc966edb617015a5d1f, 0x1e30407704b66518d96e92ecf7e298628a33652c89842718cbd45a70a8915f9e, 0x25841959f004ad6718938b0be9db7fb2a62ff813a52183eb39ab3b144eb3c174, 0x16aaf07e1f55419710cffa4ad1fd2bfc192b4c39a950f00003aa4164ced26851, 0x21b6d06608250746f4bd41caeeda22012f9aa047486971a9207f075cd42bd8aa, 0x00faeab88915c4fa2be6ab63a1e7d24ec8b3e5cf4f4ffd8b0f0a44bfa8e19ff1, 0x29e84fd058926fce0150ede6ba1e9cb72f636c9cd68ced72ef94018f968284e8, 0x0aaa342e45c92bf8e184db670da60afe2c6d64515ce0db48151c3fbddb526080, 0x22e647b6f32d6296418fab7b22fe8a5b34d5c5e88310204d3124ccf376f5118e, 0x05b3c8bc1781bf81a53c548a779f77cec5b5bf03d3621dbdb20135b99500d7a7, 0x063adb83da57a355c833e4f806c439e1a55e18b475233b39eb6455181273d713, 0x209afe06f3bbf7afc6fcc81f04c2f754f913ff6cd35d235584081664e56a41ec, 0x1ebe932f0715bc8b8b9c99cbfac3b06d9c654b268be3bb86bc55d72e23a2fbf6, 0x1eaefd7e53c9207bf81fff30729ee6d851c611a2215ffd9cc4ff0c1cc8ba093d, 0x2a54b3bcaacb4e70e4a86ecc106f486f2e54b89d37babb3bc93829ab32ad42ae, 0x2b759d20c73dd7f1aa4d495e1f495179712e04128a6bf834e21831cf939457cb, 0x08dc217216d624f0e0881883351cc2bdee7c6c9f450eec751cca9e59ddd8e254, 0x26802b71f2dc6949703ceebb3c9df6e4c8224e61bcaad8da6ab64b2d67c565b7, 0x147dbc4cfcf2003042c8baa756b4ab8218f7f55a80cbf7951a5237fa72615df6, 0x291a9f90b03dcff04e033703e32e80210858eb1e7703ba1e972935c374d1d18f, 0x18c18a611cf65c133d430b054b34793a732e358b4b3b3defd13fc7e1cd29e6ec, 0x305bb843d2395b5d452bc65f30ba62afa763fe1e67cb6fe4fcb7610327055a0a, 0x25dc37148b76b2650eec881a557989a0c1a51f0a1973a3df48784e85128c2270, 0x18dc3e4fa11737f3c8ce6b1ba2fceb7c68699d95b420f3febfd48c38eb36781d], degree_0: 2, degree_1: 16 } -point: (0x2007439461749371bb81907e508679aa89cad632956e10282a3833d7881e5ac1, 0x17f1c52e00b4bc6d7793f7456a31c85d728539dbfb2ab26f0aefd1de6fa383f0) -f_x_b: [0x189751bd92a1dd23e308c0c75dfd12fc88734b928c8aaa77887ee00b29977634, 0x2dc5a6777abfd7b1f36a70f70c2b3afdb6c45a8c9e0ee90c0f9773947c76b72a] -q_0_x_b: [0x2dc5a6777abfd7b1f36a70f70c2b3afdb6c45a8c9e0ee90c0f9773947c76b72a, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x2007439461749371bb81907e508679aa89cad632956e10282a3833d7881e5ac1 0x17f1c52e00b4bc6d7793f7456a31c85d728539dbfb2ab26f0aefd1de6fa383f0 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x263f58285d2b80bfd053eb1d9de5bee3a14b5441583ddcab104df4968c3c79dc, 0x2469ed6bd585d46e1f176cb3284f70e8ab6ccbb7da48d0624e63b92f52a00d49, 0x1c7242d5bdd893a244fc8242564d7cba9a3f3c50ba23351280267f231008ed73, 0x045dff26cabb86aeb6d6fd1b5ed8d7728a050ebb32057bf9bee015b5cc576b42, 0x17024bb2c2623e5ed9b9404b522591ccd1d2505e499224ab53deedcd5bfdba1e, 0x24b35b4e8bb0c24ad9134214b66fe644a9bb7edf8eb722ffabcd558cc21ea0df, 0x115f55aaa87ebc5a02fdc5a8d93ee5e424b63d93e942e9e4f947069804018322, 0x2ce97ace1894fd8abfbbcf832274770dbc210e42b0ea4ccd46a126aed97a3d90, 0x191268fa5edd6f0baa8b3834b5f94ff267b198ad9776e8d8939775a132b0f9a9, 0x2eee4a2ddec57b4001e5a4c066c5a2fabf3caede9e19f9ff328c557c91e03ed7, 0x28b3548d8c00077bf7dd5236315976f38f55923acb951166606fa3685a5814a1, 0x2d20a6879238ae14041b1dd80248199d245b38e77075dcf7a28da054e94efb01, 0x0ce054dbea0be6176fdcab81e4d02bb4f1c7bcf25588605aef24cab94a655f9f, 0x2dd7c00ff5b5abd429de36a6bead5f15367e2d0280d29857f352edfb5376852b, 0x225c4079e18a91469a63911fd8dd7ac8fff43579bf49de23501c43853ba84bab, 0x0696d52c794f5bff7b016dbd0ead267d389d39b139cdbdf385693b82b34f89e3, 0x11b71805720e956f3b27796ca4fc2762484903353515f277aaa7b4a8754dc6ec, 0x00ec418895cd08632982c73a7fd027704211c9395e8416a8a86f25ac4f207aac, 0x2df725b04101fc8dbc5125f26e613b684e11608ec0756d25c5fbdf8b14b957df, 0x1080ef68b157023271585a4833202a673a6a924dcee8710841fdb8c72c2df395, 0x1a1fc0ccbc99d68329143bdf973f6025010a587aa7b50ace7f7831d675d3ce20, 0x077198ca11d52b9d994b05df94f509554260224e70f2c834cd7944f9a6d22ecb, 0x23f9f4e366888f09e64868c4335a865ee9c8ba3e117cdd9fe8cde7b34fe6bc19, 0x1f3a04e7338dd5df13f6e2e909983497c5bc70a03c0e3bcc26948be41453fd3e, 0x09b1df9220c8cdaac1df01f7c52802dd05d2add8ca3c623e8d5f12e9d7b5b91b, 0x032d1ba32c6b0aa3126b44e8ba0db2bc1c22501af23ba811e36e7e1bc10d9d57, 0x02c5ea0709e1082cd5b0200644fd56d76152216ac474ea2e3a8001ec81ffee16, 0x2c695ba9b6e5efa1cb9d8acf27b14bdc7a13168f4111955bdf5d27619013fd2d, 0x020766253724235bc58c3d0b53a34f227a86b57e6a3f37c5047c93d2aebd46a9, 0x22d6011e68d2c0d573e4de0a3835f013fdc76de279e63ee2235097f50e1190bf, 0x0a8b5f237a72338aaac12169382844abd75b87c18b9fc359a95d8eb75aa379bd, 0x21abfd935f034e9cf66e94e2a02cdebf78f3bea53de0fdc9d1b191e89a2ca38a], degree_0: 2, degree_1: 16 } -point: (0x097bb197473ac1cf61ebd9c570d5d19e239d22fb68f2d98c5aefc40b664dd612, 0x053863e217745ee5315de73b00804817637e55fbbaa39f028a9e847e7a2cff93) -f_x_b: [0x008cf4ce0f4ac05d33383be937ada6461c627b24fffad925da930e2233781a58, 0x0c4a20b16ab4ea905b4a89dfec08306108d5f78f5e128ab4350df9a8e1fb0f6b] -q_0_x_b: [0x0c4a20b16ab4ea905b4a89dfec08306108d5f78f5e128ab4350df9a8e1fb0f6b, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x097bb197473ac1cf61ebd9c570d5d19e239d22fb68f2d98c5aefc40b664dd612 0x053863e217745ee5315de73b00804817637e55fbbaa39f028a9e847e7a2cff93 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x1e888e574e2cba4a4719caf11db45b5daee94a77b7c1a2c1731e49636dd29818, 0x200de346ab90c61834b08b799ae402f1cf73d54b303cf3509b38c49f37f3737c, 0x08f4037c1190c53ab34b61c3cf2a4070943614b5af58f117aad0e512213a9467, 0x24ebc345f274e4d6e299b12b7e360e5c5f2d6e1a54a25e7660e77a35d918832a, 0x0aef4586845990202a4b9c1615be205dbf63ff6fb81d0353a82d9bed02e2c9b4, 0x2e7ff08acb56886037211cbc258ac282769cf2e7524c51623bb5f5794b47f954, 0x2e74a4c9797a473d9eb5c28f1df60d988c1ff42f42c2010a691c8148251afa63, 0x2e6b1cd51d249d2c2f575b683d2c3fbd66a3eda9a1a53ef03065a1a1363dcf77, 0x25c4dfcdf17fca3c9327cf04d6617365b73058b40384ef19f64296418ffea280, 0x1ec7d4f4edb4418acbc012e105a9baab45fd07e1cad5f9b7d0371e5503b1936d, 0x08b3e2fdad1f249e3130ed1a75d0f20166e66c572c52d2c5d66065ffaf34a91e, 0x1324c8cb563cacf45d48a6bc393b2dde55661e4489b358ed478882aa9953d62b, 0x19b9e9fdf2db9bd7114fa22dae701fda01cd9efb51d1193e49201d1338c73b60, 0x1804d964fcfe17be80788bb673da6b25804800f9ff15e11ffd3880829751bf6e, 0x0b1f7798ff9e1c634ff48d2a79562aa5925de3078eafb5ed47a294c2a25d7952, 0x20d034ddf756d51483c4495457115d79c0d7c7cc4996eef7284af32336154838, 0x2f890f9dc51f8df7935950362a8e088acc834a0d6a0faa04bb238cecc104231e, 0x0b1540e5d42130958840acb6bd4aec45e1643d5298e19610dc9303a7c7294009, 0x1a1f7fda83c78c73dba2d59edf737e5b8defa7349846743d54e23d67b77fb6fd, 0x12555f2fccc7acbafbc71cf040503ec29b906dd17c033454f83ad617a39544c5, 0x06149732e9d7767092c45f77c7c4e5dc0c81df1712a0855a5bc57440371c64e0, 0x17b9ad2a9435c2928090fff847c1b2776b82a3967ce2b5346981e05063d79a69, 0x2ef81053794a0f0184cea9b17dc5a3efdada4c81026c84bf868f045daf2a53a9, 0x21c5f9fb1afa68859eae08217734d821b2dcb0f5e80eaa17f07d12d8539da4ca, 0x05c991efe718e5c6d8969aa484efe40b9c66175d37a1540217d4cca5ee0301c9, 0x183bae5520e74c05f2841bed4905cbac80c20aae49a8ec43b459ae9de37aee86, 0x22788dafa9fda69b308791663d6c790aaefd781d22b4f8670833dc5e71e13ef1, 0x19e32f5cefb16632fa877ed2fe9abec900a8a5dcb2b8790a747d163453b3753b, 0x2069dce124659cc46d7320be8f3c6ecd22fbee5215127f7bc34ede3be24b7f62, 0x1909e30bf125b3a4980b35b82e74df15dc59a7f34f431b12536d6473e7b03ab5, 0x10a4e7eb070fc9483c3f5b5d5afabd8680d170779c58e0821a0503339232bd3a, 0x22a668137b940bb07fc551a90d7fae9245c810f87416a9991d6b4b2da66c4951], degree_0: 2, degree_1: 16 } -point: (0x02b6f1c28a6867330340743a4e6c6c35bef33a4fb1dbe12f763a2825c299e214, 0x21a6a654300c1b3abccb150fc1005e90869125ddde26708665331f381d665534) -f_x_b: [0x0544cfff506ef3e8cdfbfdb884da8a076138985b641728bbad3d24c1966022f7, 0x1ba7c3201c0b12ebf6420d5a5ccff082e296662af2002776880853cb1b785820] -q_0_x_b: [0x1ba7c3201c0b12ebf6420d5a5ccff082e296662af2002776880853cb1b785820, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x02b6f1c28a6867330340743a4e6c6c35bef33a4fb1dbe12f763a2825c299e214 0x21a6a654300c1b3abccb150fc1005e90869125ddde26708665331f381d665534 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x0587866fce70dc7eafd9eb1f56538824e1123f56be7ab63ba8182722c5988f31, 0x1b78327674de659a742b7ee3313a83fca24ba726d99e03e3a18270538a9051e4, 0x197dd1b6cdf20fc9e4f989f8131f5654b9b525127302fe13ef186eeb691d0b1f, 0x08553c563c55a7c25d91c29e9daa1732fdffd673fb9464c3886c35a46a27056f, 0x2ab29ae776746f0b2f3d934aa60cbaf6d3c515104ee2dc837688ec6bb793ab38, 0x08f16b967d1dc5c31d4ae0d16291e5c565f43c46d3c99c4412236c30873ff7d8, 0x1adb0fa420e4a9592cecf613c1c20b0782f65a1aff8298ede25a1174de8a6c53, 0x034171428a415a5058a6ac2a585c714d4d5db4602ae4fcfa2adb19ed48e91287, 0x14b446e3bbd9b87bd151b09ff8d2cda2451f08370e0f1826d7de39a9afdfaeb5, 0x1b9b8ae22d3696e5301db41966949fac52a9adab611f53a0763f5de5124aba99, 0x0b42454f74046f81a2d89b338833a07fc3d3f4e8af96cd42c26105706a8537d8, 0x14bf2d2f38ce3c29f9c4c1121da5f73805b1752df0f2860db6e4862647a4bd6b, 0x036aa9d554dd07c5ed92f5e06b574baa3eb9dda405cfc1b07b7a40ca6c7e481d, 0x1874a10808e191d8f530bcea8dbd1895578bf46e8cac216d582e7f10bb1a412a, 0x1304c10c133d8ba5e598a819db919e1860f05d6d29f5b592347120b558403ee9, 0x233e97150aa31ddc24a78a3bb873efe48b30f11b777a70042bb4ec068b2cfedd, 0x0c1b57ea10c480a8e434604b1b926a3adcd9f8b2550f14bb512b2a07f635120c, 0x22c92a035c1a088918f8ffd8c26ce24ac103dda98ee4cb2d8040abfeef37da0e, 0x03e42f5239e0ae4d18682c6bcde13af80c7b847c9d53bc59bd63cc4ebc66abc4, 0x0dcb011d97150267d65873d1dc736ef47798817abcce389f6408331b09430fca, 0x1f4fd972458a79d8a8aa852f3cfa0eb86bf56d7b4e838b4c77e4c50f1f3e66ba, 0x26082233ec917c6e3680de093128fd552c5ba0959afb49f4a1c84d630b930441, 0x2e5212f6ee546f6e99e30f4610fd7b8a9faba33da8872c1887f03a3aaf5052b8, 0x113fbe0a489b8fcef723b71b02c681400d00d7eae5f4bf94acc8b0ba2799714a, 0x0b235893abee48d7dc1ebf1285c5d084c1dabbe015cac0f338103954823d2d0c, 0x129c92b91b41399aa7dbd81a2a6f4fe8a890e1ddcd5606da824c4b1924fae0e7, 0x19e3a0e4c0660fbddd60f8ded0a22c5fe219c263c0e684d15f2b37fa9cb84ccb, 0x02ce5b2907aeab24a477ba3ec29e4a5c8742a7ea1470cd9ad2db4b9031ca461f, 0x22cb6f322d33f9a2e3f47490d4291ea9b37576a684e0eaded54a9af47aa2ff38, 0x01f9f8e183c022b78fbd910424adaf26a3a2ab0c9fb3a0c2293be83edac54025, 0x0f4ef93399d9ca4ad8e48a27fd42384c865b526142c4f08a523ddb232a681fbb, 0x24dd8d182fe12463611cfdffe626571b1202697c641c67aa4a6474896e989313], degree_0: 2, degree_1: 16 } -point: (0x27285a460340604b2b67f1a5e9b5e38a8a7dc2b6372a9a53f35109c95b6af5d8, 0x13e1a085481d82ff99a62f9b3f556c1ad7387f8fc4a23dd04b2f31e1323fa9fe) -f_x_b: [0x0f0b873d546e773e143d7f0e3115249d8dda75cf6ccbad0a5d29b9d138815ca2, 0x10167124ef7b4d41771165a25457a5d7fd8e16ed7ab46775260ea8b528b70908] -q_0_x_b: [0x10167124ef7b4d41771165a25457a5d7fd8e16ed7ab46775260ea8b528b70908, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x27285a460340604b2b67f1a5e9b5e38a8a7dc2b6372a9a53f35109c95b6af5d8 0x13e1a085481d82ff99a62f9b3f556c1ad7387f8fc4a23dd04b2f31e1323fa9fe -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x133fce514e68595c90d2e338ff67d8d09faa0032164dba5203c1c752e0b5f1cf, 0x1b68468b0acd361e74fedf161e4f24bd6497669b5cc63f030ffa1ca867ee54b8, 0x091e6fddb6686c88aad43c1ec771840fe9f80ae34472c06310f03c650fb89b5e, 0x1a13affaadfa6f5b6ab6f5a21f938d91e3ceb22def9b185c5a15eb5dd10c88ba, 0x2ccd5ea9cd76b81906d53f2e1c9a81f254705e2d7e0d52258717f501ec14916c, 0x0a8bb64fd33af846d32724c8f0b5ec06d293a722755fced2d3bf05f362b953a0, 0x168a3ab12dc1bd6d4d7bef302effadaac7092a9a1901ee15a38485b167004f93, 0x0c94fa8ee5d8cae8e0ec33bd3450405f44c55aca7be9b496cded959c0e065f09, 0x2b9e5efda23775bed9b86b9ab0ab6dce197ef161988702cba90402c117f74ef2, 0x24d0769819c7e43c9e58a29b16cc3392038644004b54b41c0d187e64b5a8d9b3, 0x0ac8113cbc70fce9a4b370ee90b4151d84d9a72dcc98d70ced531a8ee7e6240b, 0x163b9165b560e9378cade928ffd3490383a2a6a76fdd07fbe635242cfca97b61, 0x24f42a975c686b6c97446556828e887ac711c2ef6521595ae1ed2041d6a0ac74, 0x08f225ef6c5fe032f9209dc0b2c706ec9f3f9887816b47e322f9e3cd39c8cd26, 0x2bdc52fd8f3d6c8d7557e230a87bb5db26e0d18b64d4cfb71e204af3cfa82bab, 0x27bdae505e0704d86e69b01c1993b23d08fefa14dfdd0ac27a1b66e4cd1bc363, 0x05891cffaf777984cf9590c203cf3118c8c9a11a23967b14c1d0d25a039fb999, 0x12e32f501d4a07ca20eb104791f74b5e751b37e27dcb830668e230063c2d2098, 0x076982c787dc51c0cda90f0f4f7a6485ac10d64bfa4d059a0cc20aaef05ed4d9, 0x3060a4e5a6c24a2238776da7285451653c1d00b28724afdbf7c9b30d16415fe3, 0x0025f6ab2f6dd866c4b2dcf4e07d7ca5dfb7dcdf37ed5e4d7756341db1da0827, 0x302958988c9bde2b6c7e9890233a3f7de086424dd0629a7e933c7f561a1c1987, 0x18114b84ef2f507771f38fba5f04d9ccc7baeb6627e56ffd996a3f8a00f8cebd, 0x18c62c36fcadd8341bd23fdf2026bc14df5332d37a165be802727fa7be0d698c, 0x1b26c72c347405ddd8c27def98ea9cc043680545df7905b95d8a66860d9097dd, 0x01068dc569b3053f954bbb46c279abaaf6c88c65ea678a63873f8fde3d4d4efc, 0x2136a60df3d2e16f54323ddd3c5ae0b314af4891c9ce9b82c43419248452e76c, 0x2c16038dd752c6bc190e3767d135519c45705582d0c735752e0dd93ccb842ace, 0x1744c1e35b0907e7d2d2a1c2eef4e9361dc086ba77c41e768875e622a97d7955, 0x2aac5fe1873be682ef1fd60f3c22ad306692848564d7657f78711e51814cab38, 0x0cdb74b50c9407456cecaaed4d7b90b5700cbe4b54ad5c45c844b44f5077f529, 0x217ee24fb39716f1cd616e31f10b4176021986bda44433114cca297420b53621], degree_0: 2, degree_1: 16 } -point: (0x1fe37b904b445f7e080a9fb3329e055c6f97b5b745a506b873f6a300b1af5c12, 0x2bf6d103387fcb8639ec4395412ae7e802c8cd2b2eafed395f4a0c25c3bcada9) -f_x_b: [0x27050b6055483298f6bda71107482329ab2e8292d05c3427ca0e3c185c1ae8be, 0x1112e38ee715cbd75f9610318ce293845a426ba5769faa70e8659db97d33fa2f] -q_0_x_b: [0x1112e38ee715cbd75f9610318ce293845a426ba5769faa70e8659db97d33fa2f, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x1fe37b904b445f7e080a9fb3329e055c6f97b5b745a506b873f6a300b1af5c12 0x2bf6d103387fcb8639ec4395412ae7e802c8cd2b2eafed395f4a0c25c3bcada9 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x272b21593adf308e46a7127eebafab68c4a62cb7140855c47d16aeb6a9d8a692, 0x0752a810d112eab5be267fbf39740b8918978e709922aaf743e367f9332af679, 0x167ce43b3ab0f4b4c8ba0af4aad552bcd4e46f86e18fd2fd3f0f492c47baf72f, 0x2e41b06b7e5b462bedbe8c7c52cf15b02d9c668dc5e4af334e4f53073644a241, 0x035bb9516a7038466cc409847075aa16dab82ff9c9ded4d3ffc44c88231b9095, 0x1169be2ac06bdaf8e530d2a510bb2b9b966c2df16b100f39444d72061ea5a76e, 0x1950eccb727c17dc6d6afc578379d5af577b541339ce06296b9dc211b3727754, 0x2b37a862de5d4c39b39daf87c7281bb78151707a9fca1bb145999acbab737795, 0x2d5019ff9e719fa13f47bc4ff01b27f155e221b8af45a30ddf6bf77090b1e410, 0x03000d9af228ac0aebaf13f62e55b731d5431be9a4e5be487e1540c06bd7d619, 0x050ac7184eef8b29717066cffa9043d617f7784ad95876b7e2770baa6520dc9b, 0x050176f6c29587c06ae5e7c752875c8c36c7de15b43180f6c110bdaae9f0d960, 0x2832baf8e45b5e26a565f23a8bca6c0923a2ba5770946846b971f1289cfc605b, 0x2c487785e91c3804962fc36b442652ee68e2ab833efb9056a1e9befa29a30038, 0x00613a4a3f6789faf024357d5493d4b7c34083a1cfacaae60b0eda1bc729712d, 0x076d423fb0b614bc17b88bea081b29ba8330f85112947bc8b17f7e093977c958, 0x0f8f90904f899f3d3cc76d7d6cad9e1fe6436a0a84bf0dcdf7b8f189f683e6d8, 0x1cc312706f6e32d648675a37cfe0cd5079f141c32af08cdc2f1e41df4fbe0f7d, 0x1f952ca62cfc34ee412e66fd08e1502af9c5cd000ad19916a5fb17f48a2f7aa6, 0x1551b8b37307d42602f97a454b53844dfa0d41c4fd3b228cae081d4e2d63ff4c, 0x1729326b72efe292e8c25cde0efaaffc411ebb883bf61ce9d742866506118d1d, 0x1bcba450a5a7042bea1b1858b0ad0b576a05acd51e980121cb6ab630bb874d8e, 0x1362eb9880782aeaedfce9bf56780b29694dfe0f9db7eec72e1f8d876534de01, 0x26409e050da41f4f09c850e6bfc0241e8f1262b118d003c65d0e52654f9adbb2, 0x13a86bfc36bd62ac1d36c30fc41de110e62e151fe83fe2d2c355a1bd0fc62a2c, 0x174d0bd7068c8c62d3d6e364f39f9b49de76a84910ecf487c43ddce955efc54b, 0x1ddf7c0f9e931ea5c64de327b1e78c88d6fb0825638c1812d9f33eb0b98e0eee, 0x0aeb33204d1bb7a84d6482b83a50a1e33612e665566e68ba87da48c35cf1c7bc, 0x1c3a9fd437ed4caf26c593e495be7f92ee64d0af6e5e307b5c2ce742a13ca163, 0x1cd42e2cf58455c5a50ce3146f34c5531dfe89b26e55daf226112a6cf038b9fd, 0x190e56d0d04b932f3e19aa64ae228cfc1c887e9241c91b63c3cea00eef455a8f, 0x12ce323ab544e51e423738d7a41112653c62593752696ccc3a1aedba910a0b3b], degree_0: 2, degree_1: 16 } -point: (0x244a46d9d45fc65ca474eaa732170b850dcd6696aa889161c9abbcc63d9e8972, 0x0bec7961dee23536cb071da46c63d28e5c8aca6225ca60406c7379961718fb9b) -f_x_b: [0x225b8322aaa243f04d96dacd8c10458263fe13d8ab94821f41d8d706d62462cc, 0x2b1101dc879ed398144e846c3d9dfe5d5e3bde2cea4a564c3b9ad0737c673941] -q_0_x_b: [0x2b1101dc879ed398144e846c3d9dfe5d5e3bde2cea4a564c3b9ad0737c673941, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x244a46d9d45fc65ca474eaa732170b850dcd6696aa889161c9abbcc63d9e8972 0x0bec7961dee23536cb071da46c63d28e5c8aca6225ca60406c7379961718fb9b -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x23c826d686e1110e290ea5a793228436d8466984ee53c37f1725f54ac1cd29e1, 0x27582862e1b0b95e4f56ef61258d3184d289515423c583a7bac901a3c1322a92, 0x2e8772a7cb985b1dbefa75edb29bdd4835c3d1f040c2e44b4051dc678802aa2a, 0x0379b1031fbee625acc4d86264f6d64cc8617edd10e091ec1dd7fca0aad2dc4f, 0x0b40732f816caaeea649a78b40b1d70f5aa9a31e46e968f3370f1687ee994193, 0x22800560cdb0d43b963f878c6698595fbe85bbb01788a6b4eaaa299245f4534a, 0x08e3b6d1e49df33dae1fc9cab8abb2ecc5eca659455763cad8aa58860e164edc, 0x1b36ecd2e0d7e0796a507309340a64a09acae4dd9aa0055d585dbc27eaa923a1, 0x21785d97572539cffe411cbb67657ddf6c89851689152264ab181fb12e7f4ad9, 0x194d359acc8f21d08523d571ebe14013442f059306250d290b9760924310be54, 0x088e9130ca95bdca74bfdf3539634ff811a9b756370e54028742470824e339c0, 0x18ec1f2d0d0de969792361b837765acaf3d356482e022025d9f5841f600390a4, 0x246d8d13602c5f830c8316ee9b11087dced2d19e56ecd5d6c9d10cb39ef80d2f, 0x0c26d4742f74f7adc81e059db1e21936452ef966a8371618f3e68188e39d1bab, 0x20d6735e2277c77fe4ebecbfbd0bdad9851cac7ee4525c5e19a995e65b60f349, 0x13c751ed9030085a206461f542c3eb43932cdc5ad798abd508f37dde8c37e0be, 0x107e6fd381b7571dd89ea969879d8967d4d6c039ed11b5b1e13b9cae079446a8, 0x1d49865d6b3e5e58da877022553c2b73b81e309b60815735634d5df2f13a1009, 0x0b887d676e126acabbca02864b162f630ae6953d7b4bfe76f12046e0fa95f643, 0x0218123eddefe2fbd0e5f390ed3c8a0d9d53182819f3b108ca1c0ad19f441f4c, 0x0f7952d85274d258733c8354b19f7162370cf1ca8428711ae818b8f2062fee63, 0x238cf87b935516e8e791da8e339e13ea7a2baffca4960c607d4146d6a911a040, 0x289f1a0d192b8160c33f3b4d0089944d0a6ed7b86a359bb942ab0b3b69a52b05, 0x0e8e5cd651a1c825d3dc41e2d289e6af150376a4fdb49ead5a414f54a45786bc, 0x2c268dbf9b93d317e2d79dca97d5055dfb4340a303145181fb043198bf489c39, 0x29b5905fc62f9c1836d316d5fa40c888fa310253d3f6422ed5f1b07c1e0d19ae, 0x1ab5623fa0a708ba16b88c49f696d3d0e2812f8820ae9c2e1b8c73ee7bddb9d7, 0x1a3b37cdd6bbb635c746d7da346d7d5342727552b4325aae86575691da207d19, 0x29f793e9f8588abe68c9edbb50ecf07a91fb65e9f71b52e12a2cc452fb1dd549, 0x2fabe6d759bbda917bab91eb63b7b30faa64319b925f15ec6eb2e9ca69bafc71, 0x09661c78abc59ffa32778a87831a1d23dfb5659065bfc61e02af7c3ffa0cd28e, 0x02756e86f36e49f45a7c73a2ca2279e4e544a2b9e49fe3f22b577a5a729cd9ba], degree_0: 2, degree_1: 16 } -point: (0x0358a2c426aa1b2f82caa46a093f14d97bcade8195afce1ed6920fbbd582894b, 0x2a0551807ff813f25d13b2b3669d1a7b530a0745dcb645ecc41bed9ac39c66f2) -f_x_b: [0x222a0fbfd1e333952588a7b0daedb10fb5f34f83f6bf769f06983475c7172dbe, 0x05a7533986644f32ae3691ef9c9f4608f9218b20d8acd23b6102d7dbae53e839] -q_0_x_b: [0x05a7533986644f32ae3691ef9c9f4608f9218b20d8acd23b6102d7dbae53e839, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x0358a2c426aa1b2f82caa46a093f14d97bcade8195afce1ed6920fbbd582894b 0x2a0551807ff813f25d13b2b3669d1a7b530a0745dcb645ecc41bed9ac39c66f2 -here2 -res: true -finished commit -poly: BivariatePolynomial { coefficients: [0x0f9535d4df4d9d66dc15ac3872cf9172c63ea8b5fd4324eb9e97d2110a22ee35, 0x284c64d51d06ff00f142964a4a3565015be1bf5c47a6a22fa669b7ba62677b1e, 0x26625c83126acb143fbd446d27e60d1eed469e9b59dc4150166455b3783b39c0, 0x0fd8c1734d6221cca4e42a1cf3e1144d9bd33b41a2af16d622bab590d647e063, 0x15828eaefd591dcc8a7fd5c474a977be951f6570b345a91e9080d6d8f8626309, 0x1820c8dad6e11e2b6fba8a13dafbc405a4b8615c7a91da0bf6f65e8247fe67a0, 0x24163aca790d878c272a72233ec45546c54d6dce8b8cf5c52be1bf8fe0f966f9, 0x1fc43a336c25849e4154bd104c15e8abbd8d9d7ad3cc4b1eaf2b998bca699a81, 0x14cdad523e75ab82bc77b55528c2e2ad185094fe30e1524dc0d30d19644a4cb9, 0x1640e54569f9f2e2b20af6f4c89a4e98f0c191b71e0bee141a854183e50655e3, 0x2f19b8db7ed8a6224b93627eab26773e02b17f87b10cb70ce3a420388a724c30, 0x2afc8396ffa251714811abb634532688919bd87470355707ec643c407041f2b9, 0x1b167a4cb3709bd5f3dfdcb8eee9506b1f0d69b0e7d7296b4d734f1a050a38b8, 0x13b2bdb76c3bfe3275910524a7bb610ec8c31a8068a1693458e95bd1b96f455b, 0x16ce4dab4d8700b595fe344944866e431aa41e66414de52db864a521421e5b35, 0x21788a2a0133359def27e48f934be18260d8d0b84be0ad5be3e77494c8b962f2, 0x00b68ba4f2cac785e1abe87fe9c4c385ce71b6e8ebe3edb23ccf666781eabc27, 0x0509b5131c056c2f671d5c4faa006086f239c665911bde430e12e5da454a0edb, 0x0497ae245d563364fb512aa5a0fe1b58f8f21c7fa64461d8018eec94b5afe112, 0x03cc2007da1db84c7bf7629f54eec10f585228d08e01a446ab063e38448c64a6, 0x19e0f845eb7f72eefbf7f4ea74ec56dd5f3152a1e9dfc6f769d3557f2ba02fd7, 0x1ece2ba9d6196e6a73cf1979f87c37d0a62ff564403fff7b77b0f212879632da, 0x255b15a1b34fd72c2ab5d0be2049c7f279435f3cfb3300547c47d6452e2e8bdc, 0x03b1b7904b326049019befab0e0884560909008d0b94ec7ade4847bfdcbea91f, 0x0488e5af6be58cab5ff153b8f660e161cfbe343a0ba4c77244e534385d89c768, 0x0c92ddbf675350df778f10f2732a9cf73780c1c47f66c1536092a79c6cdf3b9a, 0x1a946914887ea21477b7a20f34cb68c325d651c5b89fafcf313a6562d6888fb5, 0x2781ae8293b75bb14bd4202389fc1e1aac0a05081e853eb7a8a4c1281c7ab476, 0x1314f4883bfef1cc59af8111fcf9040add7873d71e2d364c6568cd148f58ecf4, 0x1cbb43bd130a22a3f7f356d257cac29b943990867dc46ed0ac3b6b127685d9b0, 0x1aa30082ceb28f106a5db12cdf870eafaab92f2d44b015486a0099c873ca118c, 0x2bfd29b664259f3eb3b14d24914ceaaff1dff99f1ab9c2369c0922a7e7c8a65b], degree_0: 2, degree_1: 16 } -point: (0x06b9752431ff00c7c5c83f86ad2f9929a91cd9bd869f58bc5846affd22e20fd9, 0x2c42b3443c3cfd584f37ecc147152b339ee69100227366286ce95623b04377fe) -f_x_b: [0x2cdd1cf6e187f5b1b517149aaff35a68e15e2485135bd77bd6d5752a06ae737e, 0x162a07c10432c5751d600749bdc2d2b8ec21f83864dc0741eb70b528d2989ff1] -q_0_x_b: [0x162a07c10432c5751d600749bdc2d2b8ec21f83864dc0741eb70b528d2989ff1, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x06b9752431ff00c7c5c83f86ad2f9929a91cd9bd869f58bc5846affd22e20fd9 0x2c42b3443c3cfd584f37ecc147152b339ee69100227366286ce95623b04377fe -here2 -res: true -m: 2, n: 4 -omega 0: 0x30644e72e131a029048b6e193fd841045cea24f6fd736bec231204708f703636 -omega 1: 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000 -n: 4 -m: 2 -start to compute the scalars -f_x_b_scalars: [0x0000000000000000000000000000000000000000000000000000000000000138, 0x30644e72e1319f812fc62248f2fb751e930ccbe3f81515c280efe4696932d181, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff31, 0x00000000000000a8888a236d8e85e33e95271c6481a45acec2f2112a86cd2e20] -lagrange scalars: [0x000000000000000000000000000000000000000000000000000000000000009c, 0x30644e72e1319fd5740b33ffba3e66bddda05a1638e74329e268ecfeac9968c1, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff99, 0x0000000000000054444511b6c742f19f4a938e3240d22d676179089543669710, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff8c, 0x000000000000003f3333cd491572353777eeaaa5b09da20d891ac66ff28cf170, 0x000000000000000000000000000000000000000000000000000000000000004e, 0x30644e72e1319fea851c786d6c0f2325b0453da2c91bce83bac72f23fd730eb5] -start to compute the affine bases -start to compute the lagrange bases -lagrange scalars: [0x000000000000000000000000000000000000000000000000000000000000009c, 0x30644e72e1319fd5740b33ffba3e66bddda05a1638e74329e268ecfeac9968c1, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff99, 0x0000000000000054444511b6c742f19f4a938e3240d22d676179089543669710, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff8c, 0x000000000000003f3333cd491572353777eeaaa5b09da20d891ac66ff28cf170, 0x000000000000000000000000000000000000000000000000000000000000004e, 0x30644e72e1319fea851c786d6c0f2325b0453da2c91bce83bac72f23fd730eb5] -finished commit -poly: BivariatePolynomial { coefficients: [0x22f570bef606bed65c7096c6a0c817e609afcfe713ba31147f8bd51b251cabeb, 0x0507ca135e47bffb64abd5ae3354a7bfdb3153434c930089dd662b20932fc330, 0x21fa0dd9f736b1f3a1a3c04aac2531ac09644d652db07c85eaeb64fa7d6e19dd, 0x23e83443e10a4ff4ab587f214216873c3fc8c6ed9f0d3bc6765a3e33825c4a27, 0x0620576f0f43be5090f4454fa5a86123628037e211520624fff8f4e060146af4, 0x2ce9baa1967d600ca9df7cca0b75f47318fc3ed448d3948930d148cef30a837f, 0x03c948203ef5a50473a68eb3f20d5ed12b1866c106d62aef7c8eced2275ef406, 0x2b19eea023ee966c87bfbf6490c791577e9c015e3a07afb209000e7190f4afee], degree_0: 4, degree_1: 2 } -point: (0x287b052408f6442905491ad99116c3d6e15673ef933dc3ee05bd02b22cf1a598, 0x0e495ae92321aac79e9db2666cc509872a1b9890585320b2c11c257b701ae079) -f_x_b: [0x0e892e919ac142923a9c14b04fe1977064b57df066909bb9f504329f07d2ce95, 0x15aa88702ff4eeffdb2918b1398ed54ac7a82021a3af554afbd21e40c277c745, 0x206ae4ddcfd8b46f3d6eac253f3be7c872a46a64c262ef6fa80d87420722cf8c, 0x06f1006603a0f604cdcecc6a96cf33764cb551649fd1dc571a9c504c7f645bad] -q_0_x_b: [0x1a7b6dc7ce5e3ccf739e2fff825616f7cc2098a6b46b9bc5936695e27ed31fc0, 0x2852fb8eed333e5fcdcae12f91da1192728f21178f9dba779f576e74ccf47365, 0x06f1006603a0f604cdcecc6a96cf33764cb551649fd1dc571a9c504c7f645bad, 0x0000000000000000000000000000000000000000000000000000000000000000] -here 0x0000000000000000000000000000000000000000000000000000000000000005 0x0000000000000000000000000000000000000000000000000000000000000007 0x287b052408f6442905491ad99116c3d6e15673ef933dc3ee05bd02b22cf1a598 0x0e495ae92321aac79e9db2666cc509872a1b9890585320b2c11c257b701ae079 -here2 -thread 'tests::test_bi_kzg_e2e' panicked at bi-kzg/src/bi_kzg.rs:391:9: -assertion `left == right` failed: pi0 != pi_0 - left: (0x1b348c4ea8e9dccc02afa645ba5258ec4184946b58a2364d074e1452cdc59eb8, 0x187841463bf7b9da9a37dfa89b522fa46b66f54402180167989c6a07c0ec8ecf) - right: (0x011d7aa1d767c13eec64a8649a3a9eff5311382528f17b2d0beef5f31a4b4445, 0x1df89f82500251aeb91db0705eb725afa27afec0b4b0f81988dcbeab060264cc) -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace - - -failures: - tests::test_bi_kzg_e2e - -test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 6 filtered out; finished in 0.13s - From 377a12294e4c86255ddd5e8a14c74492d2effe60 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Thu, 13 Jun 2024 22:39:10 -0400 Subject: [PATCH 20/31] update CI --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c925200..2e14f5dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,7 +51,8 @@ jobs: - run: wget -P data/compiler_out https://storage.googleapis.com/keccak8/circuit.txt - run: wget -P data/compiler_out https://storage.googleapis.com/keccak8/witness.txt - run: cargo test -p arith --release - - run: cargo test --no-default-features --release + - run: cargo test -p bi-kzg --release + - run: cargo test --no-default-features --release - run: cargo test --all-features --release - run: cargo run --release -- -t 4 -f 31 - run: cargo run --release -- -t 4 -f 254 @@ -72,6 +73,7 @@ jobs: - run: wget -P data/compiler_out https://storage.googleapis.com/keccak8/circuit.txt - run: wget -P data/compiler_out https://storage.googleapis.com/keccak8/witness.txt - run: RUSTFLAGS="-C target-feature=+avx2" cargo test -p arith --release + - run: RUSTFLAGS="-C target-feature=+avx2" cargo test -p bi-kzg --release - run: RUSTFLAGS="-C target-feature=+avx2" cargo test --no-default-features --release - run: RUSTFLAGS="-C target-feature=+avx2" cargo test --all-features --release - run: RUSTFLAGS="-C target-feature=+avx2" cargo run --release -- -t 4 -f 31 From 5165f4ab4f166d85a5a1c2abb29f783af481f030 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Thu, 13 Jun 2024 22:39:59 -0400 Subject: [PATCH 21/31] clean up --- bi-kzg/msm_bench.log | 148 ------------------------------------------- 1 file changed, 148 deletions(-) delete mode 100644 bi-kzg/msm_bench.log diff --git a/bi-kzg/msm_bench.log b/bi-kzg/msm_bench.log deleted file mode 100644 index 7e53be81..00000000 --- a/bi-kzg/msm_bench.log +++ /dev/null @@ -1,148 +0,0 @@ - -running 4 tests -test poly::tests::test_bivariate_poly_eval ... ignored -test tests::test_bi_kzg_e2e ... ignored -test tests::test_lagrange_eval ... ignored -test tests::test_tensor_product ... ignored - -test result: ok. 0 passed; 0 failed; 4 ignored; 0 measured; 0 filtered out; finished in 0.00s - -arkworks MSM with degree 2048 - time: [1.8813 ms 1.9146 ms 1.9416 ms] - change: [+0.9709% +3.6059% +6.1557%] (p = 0.02 < 0.05) - Change within noise threshold. - -custimzied MSM with degree 2048, cpu=4 - time: [20.146 ms 20.382 ms 20.545 ms] - change: [+1.4738% +2.1380% +2.8502%] (p = 0.00 < 0.05) - Performance has regressed. - -custimzied MSM with degree 2048, cpu=8 - time: [14.017 ms 14.092 ms 14.181 ms] - change: [+1.1103% +1.5606% +2.1108%] (p = 0.00 < 0.05) - Performance has regressed. - -custimzied MSM with degree 2048, cpu=16 - time: [9.9906 ms 10.390 ms 10.934 ms] - change: [+0.8012% +7.7360% +14.804%] (p = 0.06 > 0.05) - No change in performance detected. - -custimzied MSM with degree 2048, cpu=32 - time: [9.2362 ms 9.6546 ms 10.492 ms] - change: [+2.9217% +7.4933% +14.080%] (p = 0.01 < 0.05) - Performance has regressed. -Found 1 outliers among 10 measurements (10.00%) - 1 (10.00%) high severe - -halo2 MSM with degree 2048 - time: [1.9300 ms 1.9571 ms 1.9810 ms] - change: [-3.9822% -1.4495% +0.8075%] (p = 0.30 > 0.05) - No change in performance detected. - -arkworks MSM with degree 4096 - time: [3.0241 ms 3.0370 ms 3.0486 ms] - change: [-0.5062% +0.9064% +2.7110%] (p = 0.30 > 0.05) - No change in performance detected. -Found 1 outliers among 10 measurements (10.00%) - 1 (10.00%) high severe - -custimzied MSM with degree 4096, cpu=4 - time: [26.259 ms 26.312 ms 26.380 ms] - change: [-0.5045% -0.0611% +0.3729%] (p = 0.80 > 0.05) - No change in performance detected. - -custimzied MSM with degree 4096, cpu=8 - time: [20.298 ms 20.364 ms 20.449 ms] - change: [+0.7966% +1.1451% +1.4964%] (p = 0.00 < 0.05) - Change within noise threshold. -Found 2 outliers among 10 measurements (20.00%) - 1 (10.00%) high mild - 1 (10.00%) high severe - -custimzied MSM with degree 4096, cpu=16 - time: [15.431 ms 15.823 ms 16.253 ms] - change: [+2.3820% +6.4428% +10.587%] (p = 0.01 < 0.05) - Performance has regressed. - -custimzied MSM with degree 4096, cpu=32 - time: [15.421 ms 15.668 ms 16.016 ms] - change: [+1.0481% +3.5925% +6.0496%] (p = 0.02 < 0.05) - Performance has regressed. - -halo2 MSM with degree 4096 - time: [3.2928 ms 3.3259 ms 3.3476 ms] - change: [+1.4265% +3.5407% +5.6867%] (p = 0.01 < 0.05) - Performance has regressed. -Found 2 outliers among 10 measurements (20.00%) - 2 (20.00%) high mild - -arkworks MSM with degree 8192 - time: [6.0368 ms 6.0925 ms 6.1836 ms] - change: [-0.1292% +0.8006% +1.7551%] (p = 0.13 > 0.05) - No change in performance detected. - -custimzied MSM with degree 8192, cpu=4 - time: [36.229 ms 36.595 ms 36.980 ms] - change: [-1.1925% -0.2872% +0.6541%] (p = 0.58 > 0.05) - No change in performance detected. -Found 1 outliers among 10 measurements (10.00%) - 1 (10.00%) high severe - -custimzied MSM with degree 8192, cpu=8 - time: [27.268 ms 27.671 ms 28.016 ms] - change: [+0.4422% +1.6677% +3.3659%] (p = 0.02 < 0.05) - Change within noise threshold. -Found 1 outliers among 10 measurements (10.00%) - 1 (10.00%) high mild - -custimzied MSM with degree 8192, cpu=16 - time: [24.551 ms 26.576 ms 30.854 ms] - change: [+14.974% +27.059% +38.138%] (p = 0.00 < 0.05) - Performance has regressed. - -custimzied MSM with degree 8192, cpu=32 - time: [30.187 ms 32.344 ms 33.676 ms] - change: [+7.7978% +21.365% +33.128%] (p = 0.00 < 0.05) - Performance has regressed. - -halo2 MSM with degree 8192 - time: [5.4164 ms 5.5585 ms 5.6674 ms] - change: [-1.8822% +1.3195% +4.3651%] (p = 0.46 > 0.05) - No change in performance detected. - -arkworks MSM with degree 16384 - time: [11.135 ms 11.229 ms 11.374 ms] - change: [+0.3314% +1.1181% +2.0262%] (p = 0.02 < 0.05) - Change within noise threshold. -Found 1 outliers among 10 measurements (10.00%) - 1 (10.00%) high severe - -custimzied MSM with degree 16384, cpu=4 - time: [54.622 ms 54.782 ms 54.994 ms] - change: [-0.5004% +0.0082% +0.5118%] (p = 0.98 > 0.05) - No change in performance detected. - -custimzied MSM with degree 16384, cpu=8 - time: [36.885 ms 37.015 ms 37.112 ms] - change: [-0.6465% +0.0691% +0.7008%] (p = 0.85 > 0.05) - No change in performance detected. - -custimzied MSM with degree 16384, cpu=16 - time: [28.828 ms 29.302 ms 30.060 ms] - change: [-4.1606% -0.3888% +3.8239%] (p = 0.86 > 0.05) - No change in performance detected. -Found 1 outliers among 10 measurements (10.00%) - 1 (10.00%) high mild - -custimzied MSM with degree 16384, cpu=32 - time: [46.855 ms 51.795 ms 57.535 ms] - change: [+41.566% +52.171% +63.184%] (p = 0.00 < 0.05) - Performance has regressed. - -halo2 MSM with degree 16384 - time: [9.8853 ms 10.604 ms 11.531 ms] - change: [+15.404% +21.090% +25.905%] (p = 0.00 < 0.05) - Performance has regressed. -Found 1 outliers among 10 measurements (10.00%) - 1 (10.00%) low mild - From 72e386da5f2d6668b5db46fab13676647f34f974 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Sun, 16 Jun 2024 20:45:43 -0400 Subject: [PATCH 22/31] fix clippy --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1fe0ccbd..beb606ae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ members = [ ark-std = "0.4" ark-bn254 = "0.4.0" ark-ec = "0.4.0" -ark-ff = { version = "0.4", features = [ "asm" ] } +ark-ff = { version = "0.4" } clap = { version = "4.1", features = ["derive"] } criterion = { version = "0.5", features = ["html_reports"] } itertools = "0.13" @@ -37,4 +37,4 @@ rand = "0.8.5" rayon = "1.10" sha2 = "0.10.8" -halo2curves = { git = "https://github.com/zhenfeizhang/halo2curves", default-features = false, features = [ "bits", "asm", "bn256-table" ] } +halo2curves = { git = "https://github.com/zhenfeizhang/halo2curves", default-features = false, features = [ "bits", "bn256-table" ] } From 14b1f1499ac79afb33eaaf032a66c5084c6386be Mon Sep 17 00:00:00 2001 From: zhenfei Date: Sun, 16 Jun 2024 21:13:41 -0400 Subject: [PATCH 23/31] finished benchmark --- .gitignore | 1 + bi-kzg/Cargo.toml | 1 + bi-kzg/benches/bi_kzg_bench.rs | 188 ++++++++++++--------------------- bi-kzg/src/bi_kzg.rs | 26 ++++- bi-kzg/src/lib.rs | 1 + bi-kzg/src/msm.rs | 9 +- bi-kzg/src/poly.rs | 13 ++- bi-kzg/src/tests.rs | 19 ++++ 8 files changed, 125 insertions(+), 133 deletions(-) diff --git a/.gitignore b/.gitignore index e0195edd..b863d1fc 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,4 @@ perf.data.old flamegraph.svg output.txt .DS_Store +*.log \ No newline at end of file diff --git a/bi-kzg/Cargo.toml b/bi-kzg/Cargo.toml index 78005917..3a050578 100644 --- a/bi-kzg/Cargo.toml +++ b/bi-kzg/Cargo.toml @@ -26,5 +26,6 @@ harness = false [features] default = [ + "ark-std/print-trace", "ark-ec/parallel", ] \ No newline at end of file diff --git a/bi-kzg/benches/bi_kzg_bench.rs b/bi-kzg/benches/bi_kzg_bench.rs index c5e687dc..445ba719 100644 --- a/bi-kzg/benches/bi_kzg_bench.rs +++ b/bi-kzg/benches/bi_kzg_bench.rs @@ -1,154 +1,96 @@ -use ark_bn254::{Fr, G1Affine, G1Projective}; -use ark_ec::Group; -use ark_ec::{AffineRepr, VariableBaseMSM}; -use ark_ff::Zero; -use ark_ff::{PrimeField, UniformRand}; -use halo2curves::bn256; +use bi_kzg::{BiKZG, BiKZGVerifierParam, BivariatePolynomial, PolynomialCommitmentScheme}; +use halo2curves::bn256::{self, Bn256, Fr}; use halo2curves::ff::Field; use halo2curves::msm::best_multiexp; -use std::{thread, time::Duration}; +use std::time::Duration; -use criterion::{criterion_group, criterion_main, Criterion}; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; -fn criterion_benchmark(c: &mut Criterion) { +fn bench_msm(c: &mut Criterion) { let degree_set = vec![2048, 4096, 8192, 16384]; - //let degree_set = vec![32786]; - // let mut res = vec![]; for degree in degree_set { let mut rng = rand::thread_rng(); let affine_bases = (0..degree) - .map(|_| G1Affine::rand(&mut rng)) - .collect::>(); - let proj_bases = affine_bases - .iter() - .map(|g| g.into_group()) + .map(|_| bn256::G1Affine::random(&mut rng)) .collect::>(); - let scalars = (0..degree).map(|_| Fr::rand(&mut rng)).collect::>(); - c.bench_function(&format!("arkworks MSM with degree {}", degree), |b| { + let scalars = (0..degree) + .map(|_| bn256::Fr::random(&mut rng)) + .collect::>(); + c.bench_function(&format!("halo2 MSM with degree {}", degree), |b| { b.iter(|| { - _ = G1Projective::msm(&affine_bases, &scalars); + _ = best_multiexp(&scalars, &affine_bases); }); }); + } +} - let cpu_set = vec![4, 8, 16, 32]; - for nb_cpu in cpu_set.iter() { +fn bench_commit(c: &mut Criterion) { + let degree_set = vec![4usize, 16, 64, 256]; + let mut rng = rand::thread_rng(); + for °ree_0 in degree_set.iter() { + for °ree_1 in degree_set.iter() { + let srs = BiKZG::::gen_srs_for_testing(&mut rng, degree_0, degree_1); + let vk = BiKZGVerifierParam::::from(&srs); + let poly = BivariatePolynomial::::random(&mut rng, degree_0, degree_1); c.bench_function( - &format!("custimzied MSM with degree {}, cpu={}", degree, nb_cpu), + &format!("bi-kzg commit with degrees {} {}", degree_0, degree_1), |b| { b.iter(|| { - _ = quick_exp(&proj_bases, &scalars, *nb_cpu); + let _ = black_box(BiKZG::::commit(&srs, &poly)); }); }, ); - } - let affine_bases = (0..degree) - .map(|_| bn256::G1Affine::random(&mut rng)) - .collect::>(); + let com = BiKZG::::commit(&srs, &poly); - let scalars = (0..degree) - .map(|_| bn256::Fr::random(&mut rng)) - .collect::>(); - c.bench_function(&format!("halo2 MSM with degree {}", degree), |b| { - b.iter(|| { - _ = best_multiexp(&scalars, &affine_bases); - }); - }); + let points = (0..10) + .map(|_| (Fr::random(&mut rng), Fr::random(&mut rng))) + .collect::>(); + c.bench_function( + &format!( + "bi-kzg open {} points with degrees {} {}", + points.len(), + degree_0, + degree_1 + ), + |b| { + b.iter(|| { + let _ = points + .iter() + .map(|p| BiKZG::::open(&srs, &poly, p)) + .collect::>(); + }); + }, + ); + let proofs = points + .iter() + .map(|p| BiKZG::::open(&srs, &poly, p)) + .collect::>(); + + c.bench_function( + &format!( + "bi-kzg verify {} points with degrees {} {}", + points.len(), + degree_0, + degree_1 + ), + |b| { + b.iter(|| { + points.iter().zip(proofs.iter()).for_each(|(p, proof)| { + assert!(BiKZG::::verify(&vk, &com, p, &proof.1, &proof.0)) + }) + }); + }, + ); + } } } criterion_group! { name = benches; config = Criterion::default().sample_size(10).measurement_time(Duration::from_secs(2)).warm_up_time(Duration::from_secs(1)); - targets = criterion_benchmark + targets = bench_msm, bench_commit } criterion_main!(benches); - -pub fn quick_exp(points: &Vec, scalars: &Vec, num_cpu: usize) -> G1Projective { - let c = best_c(points.len(), num_cpu); - assert!(64 % c == 0); - - let mut result = G1Projective::zero(); - let nb_fr_bits = nb_fr_bits(); - - let point_len = points.len(); - let num_points_per_cpu = (point_len + num_cpu - 1) / num_cpu; - - let mut handles = vec![]; - - let point_ptr_usize = points.as_ptr() as usize; - let scalar_ptr_usize = scalars.as_ptr() as usize; - for i in 0..num_cpu { - let handle = thread::spawn(move || { - let mut bucket = vec![G1Projective::zero(); (nb_fr_bits / c) * (1 << c)]; - let start = i * num_points_per_cpu; - let end = std::cmp::min((i + 1) * num_points_per_cpu, point_len); - let point_ptr = point_ptr_usize as *const G1Projective; - let scalar_ptr = scalar_ptr_usize as *const Fr; - for j in start..end { - let point = unsafe { point_ptr.add(j).read() }; - let scalar_bigint = unsafe { scalar_ptr.add(j).read() }; - let limbs = scalar_bigint.into_bigint().0; - for k in 0..(nb_fr_bits / c) { - let mut temp = limbs[(k * c) / 64]; - let inside_idx = (k * c) % 64; - temp >>= inside_idx; - temp &= (1 << c) - 1; - bucket[(k << c) + temp as usize] += point; - } - } - let mut partial_sum = G1Projective::zero(); - for i in (0..(nb_fr_bits / c)).rev() { - for _ in 0..c { - partial_sum.double_in_place(); - } - let mut tmp = G1Projective::zero(); - for j in 0..(1 << c) { - let mut pow_res = G1Projective::zero(); - let mut base = bucket[(i << c) + j]; - for k in 0..c { - if (j >> k) & 1 == 1 { - pow_res += base; - } - base.double_in_place(); - } - tmp += pow_res; - } - partial_sum += tmp; - } - partial_sum - }); - handles.push(handle); - } - for handle in handles { - let partial_sum = handle.join().unwrap(); - result += partial_sum; - } - result -} - -#[inline] -fn nb_fr_bits() -> usize { - 256 -} - -#[inline] -fn cost_c(len: usize, c: usize, num_cpu: usize) -> usize { - let mut sum = 0_usize; - //first part - sum += (nb_fr_bits() / c) * len / num_cpu; - //second part - sum += nb_fr_bits() * (1 << c); - sum -} - -#[inline] -fn best_c(len: usize, num_cpu: usize) -> usize { - if cost_c(len, 8, num_cpu) > cost_c(len, 16, num_cpu) { - 16 - } else { - 8 - } -} diff --git a/bi-kzg/src/bi_kzg.rs b/bi-kzg/src/bi_kzg.rs index 5b619f27..4ec1db68 100644 --- a/bi-kzg/src/bi_kzg.rs +++ b/bi-kzg/src/bi_kzg.rs @@ -1,6 +1,7 @@ use std::ops::Add; use std::{borrow::Borrow, marker::PhantomData}; +use ark_std::{end_timer, start_timer}; use halo2curves::ff::Field; use halo2curves::ff::PrimeField; use halo2curves::group::prime::PrimeCurveAffine; @@ -70,7 +71,7 @@ where (omega_0, omega_1) }; - println!("start to compute the scalars"); + // println!("start to compute the scalars"); // computes the vector of L_i^N(tau_0) * L_j^M(tau_1) for i in 0..supported_n and j in 0..supported_m let (scalars, lagrange_scalars) = { let powers_of_omega_0 = powers_of_field_elements(&omega_0, supported_n); @@ -85,7 +86,7 @@ where (scalars, lagrange_scalars) }; - println!("start to compute the affine bases"); + // println!("start to compute the affine bases"); let coeff_bases = { let mut proj_bases = vec![E::G1::identity(); supported_n * supported_m]; parallelize(&mut proj_bases, |g, start| { @@ -103,7 +104,7 @@ where g_bases }; - println!("start to compute the lagrange bases"); + // println!("start to compute the lagrange bases"); let lagrange_bases = { let mut proj_bases = vec![E::G1::identity(); supported_n * supported_m]; @@ -148,6 +149,11 @@ where prover_param: impl Borrow, poly: &Self::Polynomial, ) -> Self::Commitment { + let timer = start_timer!(|| format!( + "Committing to polynomial of degree {} {}", + poly.degree_0, poly.degree_1 + )); + let com = best_multiexp( &poly.coefficients, prover_param.borrow().powers_of_g.as_slice(), @@ -171,6 +177,8 @@ where ); } + end_timer!(timer); + Self::Commitment { com } } @@ -179,10 +187,16 @@ where polynomial: &Self::Polynomial, point: &Self::Point, ) -> (Self::Proof, Self::Evaluation) { + let timer = start_timer!(|| format!( + "Opening polynomial of degree {} {}", + polynomial.degree_0, polynomial.degree_1 + )); + let a = point.0; let b = point.1; let u = polynomial.evaluate(&a, &b); + let timer2 = start_timer!(|| "Computing the proof pi0"); let (pi_0, f_x_b) = { let f_x_b = polynomial.evaluate_y(&point.1); let mut q_0_x_b = f_x_b.clone(); @@ -196,7 +210,9 @@ where .to_affine(); (pi_0, f_x_b) }; + end_timer!(timer2); + let timer2 = start_timer!(|| "Computing the proof pi1"); let pi_1 = { let mut t = polynomial.clone(); t.coefficients @@ -236,18 +252,18 @@ where &q_1_x_y, prover_param .borrow() - // .powers_of_g .powers_of_g_lagrange_over_both_roots .as_ref(), ) .to_affine() }; - + end_timer!(timer2); let proof = BiKZGProof:: { pi0: pi_0, pi1: pi_1, }; + end_timer!(timer); (proof, u) } diff --git a/bi-kzg/src/lib.rs b/bi-kzg/src/lib.rs index 4d557237..0600a294 100644 --- a/bi-kzg/src/lib.rs +++ b/bi-kzg/src/lib.rs @@ -7,6 +7,7 @@ mod structs; mod tests; mod util; +pub use bi_kzg::BiKZG; pub use pcs::PolynomialCommitmentScheme; pub use structs::BivariatePolynomial; pub use structs::{BiKZGCommitment, BiKZGProof, BiKZGSRS, BiKZGVerifierParam}; diff --git a/bi-kzg/src/msm.rs b/bi-kzg/src/msm.rs index 79d56f15..0769c2fd 100644 --- a/bi-kzg/src/msm.rs +++ b/bi-kzg/src/msm.rs @@ -3,6 +3,7 @@ use std::ops::{Add, Neg}; +use ark_std::{end_timer, start_timer}; use halo2curves::ff::PrimeField; use halo2curves::group::Group; use halo2curves::pairing::PairingCurveAffine; @@ -60,10 +61,11 @@ pub fn best_multiexp>( coeffs: &[C::Scalar], bases: &[C], ) -> C::Curve { + let timer = start_timer!(|| format!("Multiexp of dim {}", coeffs.len())); assert_eq!(coeffs.len(), bases.len()); let num_threads = rayon::current_num_threads(); - if coeffs.len() > num_threads { + let res = if coeffs.len() > num_threads { let chunk = coeffs.len() / num_threads; let num_chunks = coeffs.chunks(chunk).len(); let mut results = vec![C::Curve::identity(); num_chunks]; @@ -85,7 +87,10 @@ pub fn best_multiexp>( let mut acc = C::Curve::identity(); multiexp_serial(coeffs, bases, &mut acc); acc - } + }; + + end_timer!(timer); + res } pub fn multiexp_serial>( diff --git a/bi-kzg/src/poly.rs b/bi-kzg/src/poly.rs index 794ea003..7f3f3909 100644 --- a/bi-kzg/src/poly.rs +++ b/bi-kzg/src/poly.rs @@ -1,3 +1,4 @@ +use ark_std::{end_timer, start_timer}; use halo2curves::ff::{Field, PrimeField}; use itertools::Itertools; use rand::RngCore; @@ -58,7 +59,13 @@ impl BivariatePolynomial { } /// + // TODO: this is super slow. Implement FFT for bivariate polynomials. pub fn lagrange_coeffs(&self) -> Vec { + let timer = start_timer!(|| format!( + "Lagrange coefficients of degree {} {}", + self.degree_0, self.degree_1 + )); + // roots of unity for supported_n and supported_m let (omega_0, omega_1) = { let omega = F::ROOT_OF_UNITY; @@ -85,10 +92,9 @@ impl BivariatePolynomial { res.push(self.evaluate(omega_0_power, omega_1_power)); } } - + end_timer!(timer); res } - } /// For x in points, compute the Lagrange coefficients at x given the roots. @@ -116,6 +122,7 @@ pub(crate) fn lagrange_coefficients(roots: &[F], points: /// // TODO: this algorithm is quadratic. is this more efficient than FFT? pub(crate) fn univariate_quotient(poly: &[F], point: &F) -> Vec { + let timer = start_timer!(|| format!("Univariate quotient of degree {}", poly.len())); let mut dividend_coeff = poly.to_vec(); let divisor = vec![-*point, F::from(1u64)]; let mut coefficients = vec![]; @@ -141,7 +148,7 @@ pub(crate) fn univariate_quotient(poly: &[F], point: &F) -> Vec::gen_srs_for_testing(&mut rng, n, m); + let vk = BiKZGVerifierParam::::from(&srs); + + let poly = BivariatePolynomial::::random(&mut rng, n, m); + + let x = Fr::random(&mut rng); + let y = Fr::random(&mut rng); + + let commit = BiKZG::::commit(&srs, &poly); + let (proof, eval) = BiKZG::::open(&srs, &poly, &(x, y)); + assert!(BiKZG::::verify(&vk, &commit, &(x, y), &eval, &proof)); +} + #[test] fn test_bi_kzg_e2e() { let mut rng = test_rng(); From 755be3fc40f64bca396fdc2a79f69c305f15ffcd Mon Sep 17 00:00:00 2001 From: zhenfei Date: Tue, 18 Jun 2024 11:44:39 -0400 Subject: [PATCH 24/31] wip --- bi-kzg/benches/bi_kzg_bench.rs | 16 +- bi-kzg/src/bi_fft.rs | 1 + .../src/{bi_kzg.rs => coeff_form_bi_kzg.rs} | 48 +-- bi-kzg/src/lagrange_form_bi_kzg.rs | 305 ++++++++++++++++++ bi-kzg/src/lib.rs | 11 +- bi-kzg/src/msm.rs | 171 ---------- bi-kzg/src/tests.rs | 47 ++- 7 files changed, 371 insertions(+), 228 deletions(-) create mode 100644 bi-kzg/src/bi_fft.rs rename bi-kzg/src/{bi_kzg.rs => coeff_form_bi_kzg.rs} (90%) create mode 100644 bi-kzg/src/lagrange_form_bi_kzg.rs delete mode 100644 bi-kzg/src/msm.rs diff --git a/bi-kzg/benches/bi_kzg_bench.rs b/bi-kzg/benches/bi_kzg_bench.rs index 445ba719..9dad759d 100644 --- a/bi-kzg/benches/bi_kzg_bench.rs +++ b/bi-kzg/benches/bi_kzg_bench.rs @@ -1,4 +1,4 @@ -use bi_kzg::{BiKZG, BiKZGVerifierParam, BivariatePolynomial, PolynomialCommitmentScheme}; +use bi_kzg::{BiKZGVerifierParam, BivariatePolynomial, CoeffFormBiKZG, PolynomialCommitmentScheme}; use halo2curves::bn256::{self, Bn256, Fr}; use halo2curves::ff::Field; use halo2curves::msm::best_multiexp; @@ -31,19 +31,19 @@ fn bench_commit(c: &mut Criterion) { let mut rng = rand::thread_rng(); for °ree_0 in degree_set.iter() { for °ree_1 in degree_set.iter() { - let srs = BiKZG::::gen_srs_for_testing(&mut rng, degree_0, degree_1); + let srs = CoeffFormBiKZG::::gen_srs_for_testing(&mut rng, degree_0, degree_1); let vk = BiKZGVerifierParam::::from(&srs); let poly = BivariatePolynomial::::random(&mut rng, degree_0, degree_1); c.bench_function( &format!("bi-kzg commit with degrees {} {}", degree_0, degree_1), |b| { b.iter(|| { - let _ = black_box(BiKZG::::commit(&srs, &poly)); + let _ = black_box(CoeffFormBiKZG::::commit(&srs, &poly)); }); }, ); - let com = BiKZG::::commit(&srs, &poly); + let com = CoeffFormBiKZG::::commit(&srs, &poly); let points = (0..10) .map(|_| (Fr::random(&mut rng), Fr::random(&mut rng))) @@ -59,14 +59,14 @@ fn bench_commit(c: &mut Criterion) { b.iter(|| { let _ = points .iter() - .map(|p| BiKZG::::open(&srs, &poly, p)) + .map(|p| CoeffFormBiKZG::::open(&srs, &poly, p)) .collect::>(); }); }, ); let proofs = points .iter() - .map(|p| BiKZG::::open(&srs, &poly, p)) + .map(|p| CoeffFormBiKZG::::open(&srs, &poly, p)) .collect::>(); c.bench_function( @@ -79,7 +79,9 @@ fn bench_commit(c: &mut Criterion) { |b| { b.iter(|| { points.iter().zip(proofs.iter()).for_each(|(p, proof)| { - assert!(BiKZG::::verify(&vk, &com, p, &proof.1, &proof.0)) + assert!(CoeffFormBiKZG::::verify( + &vk, &com, p, &proof.1, &proof.0 + )) }) }); }, diff --git a/bi-kzg/src/bi_fft.rs b/bi-kzg/src/bi_fft.rs new file mode 100644 index 00000000..d20697ac --- /dev/null +++ b/bi-kzg/src/bi_fft.rs @@ -0,0 +1 @@ +//! Two layer FFT and its inverse diff --git a/bi-kzg/src/bi_kzg.rs b/bi-kzg/src/coeff_form_bi_kzg.rs similarity index 90% rename from bi-kzg/src/bi_kzg.rs rename to bi-kzg/src/coeff_form_bi_kzg.rs index 4ec1db68..ecd4a85b 100644 --- a/bi-kzg/src/bi_kzg.rs +++ b/bi-kzg/src/coeff_form_bi_kzg.rs @@ -1,4 +1,3 @@ -use std::ops::Add; use std::{borrow::Borrow, marker::PhantomData}; use ark_std::{end_timer, start_timer}; @@ -7,27 +6,32 @@ use halo2curves::ff::PrimeField; use halo2curves::group::prime::PrimeCurveAffine; use halo2curves::group::Curve; use halo2curves::group::Group; +use halo2curves::msm::best_multiexp; use halo2curves::pairing::{MillerLoopResult, MultiMillerLoop}; +use halo2curves::CurveAffine; use itertools::Itertools; use rand::RngCore; -use crate::msm::best_multiexp; +// use crate::msm::best_multiexp; use crate::poly::{lagrange_coefficients, univariate_quotient}; use crate::structs::BivariatePolynomial; use crate::util::parallelize; +// use crate::LagrangeFormBiKZG; use crate::{ pcs::PolynomialCommitmentScheme, util::{powers_of_field_elements, tensor_product_parallel}, BiKZGCommitment, BiKZGProof, BiKZGSRS, BiKZGVerifierParam, }; -pub struct BiKZG { +/// Commit to the bi-variate polynomial in its coefficient form. +/// Note that it is in general more efficient to use the lagrange form. +pub struct CoeffFormBiKZG { _phantom: PhantomData, } -impl PolynomialCommitmentScheme for BiKZG +impl PolynomialCommitmentScheme for CoeffFormBiKZG where - E::G1Affine: Add, + E::G1Affine: CurveAffine, { type SRS = BiKZGSRS; type ProverParam = BiKZGSRS; @@ -39,11 +43,9 @@ where type Point = (E::Fr, E::Fr); type BatchProof = Vec; - fn gen_srs_for_testing( - mut rng: impl RngCore, - supported_n: usize, - supported_m: usize, - ) -> Self::SRS { + fn gen_srs_for_testing(mut rng: impl RngCore, supported_n: usize, supported_m: usize) -> Self::SRS { + // LagrangeFormBiKZG::::gen_srs_for_testing(rng, supported_n, supported_m) + assert!(supported_n.is_power_of_two()); assert!(supported_m.is_power_of_two()); @@ -87,12 +89,13 @@ where }; // println!("start to compute the affine bases"); + let g1_prog = g1.to_curve(); let coeff_bases = { let mut proj_bases = vec![E::G1::identity(); supported_n * supported_m]; parallelize(&mut proj_bases, |g, start| { for (idx, g) in g.iter_mut().enumerate() { let offset = start + idx; - *g = g1 * scalars[offset]; + *g = g1_prog * scalars[offset]; } }); @@ -157,29 +160,11 @@ where let com = best_multiexp( &poly.coefficients, prover_param.borrow().powers_of_g.as_slice(), - ) - .into(); - - #[cfg(test)] - { - let lag_coeff = poly.lagrange_coeffs(); - let com_lag = best_multiexp( - &lag_coeff, - prover_param - .borrow() - .powers_of_g_lagrange_over_both_roots - .as_slice(), - ) - .into(); - assert_eq!( - com, com_lag, - "commitment is not equal to lagrange commitment" - ); - } + ); end_timer!(timer); - Self::Commitment { com } + Self::Commitment { com: com.into() } } fn open( @@ -302,7 +287,6 @@ where _polynomials: &[Self::Polynomial], _points: &[Self::Point], _evals: &[Self::Evaluation], - // _transcript: &mut IOPTranscript, ) -> Self::BatchProof { unimplemented!() } diff --git a/bi-kzg/src/lagrange_form_bi_kzg.rs b/bi-kzg/src/lagrange_form_bi_kzg.rs new file mode 100644 index 00000000..e7becd01 --- /dev/null +++ b/bi-kzg/src/lagrange_form_bi_kzg.rs @@ -0,0 +1,305 @@ +use std::{borrow::Borrow, marker::PhantomData}; + +use ark_std::{end_timer, start_timer}; +use halo2curves::ff::Field; +use halo2curves::ff::PrimeField; +use halo2curves::group::prime::PrimeCurveAffine; +use halo2curves::group::Curve; +use halo2curves::group::Group; +use halo2curves::msm::best_multiexp; +use halo2curves::pairing::{MillerLoopResult, MultiMillerLoop}; +use halo2curves::CurveAffine; +use itertools::Itertools; +use rand::RngCore; + +use crate::poly::{lagrange_coefficients, univariate_quotient}; +use crate::structs::BivariateLagrangePolynomial; +use crate::util::parallelize; +use crate::{ + pcs::PolynomialCommitmentScheme, + util::{powers_of_field_elements, tensor_product_parallel}, + BiKZGCommitment, BiKZGProof, BiKZGSRS, BiKZGVerifierParam, +}; + +/// Commit to the bi-variate polynomial in its lagrange form. +/// this should be the preferred form for commitment. +pub struct LagrangeFormBiKZG { + _phantom: PhantomData, +} + +impl PolynomialCommitmentScheme for LagrangeFormBiKZG +where + E::G1Affine: CurveAffine, +{ + type SRS = BiKZGSRS; + type ProverParam = BiKZGSRS; + type VerifierParam = BiKZGVerifierParam; + type Polynomial = BivariateLagrangePolynomial; + type Commitment = BiKZGCommitment; + type Proof = BiKZGProof; + type Evaluation = E::Fr; + type Point = (E::Fr, E::Fr); + type BatchProof = Vec; + + fn gen_srs_for_testing( + mut rng: impl RngCore, + supported_n: usize, + supported_m: usize, + ) -> Self::SRS { + assert!(supported_n.is_power_of_two()); + assert!(supported_m.is_power_of_two()); + + let tau_0 = E::Fr::random(&mut rng); + let tau_1 = E::Fr::random(&mut rng); + // let tau_0 = E::Fr::from(5); + // let tau_1 = E::Fr::from(7); + + let g1 = E::G1Affine::generator(); + + // roots of unity for supported_n and supported_m + let (omega_0, omega_1) = { + let omega = E::Fr::ROOT_OF_UNITY; + let omega_0 = omega.pow_vartime(&[(1 << E::Fr::S) / supported_n as u64]); + let omega_1 = omega.pow_vartime(&[(1 << E::Fr::S) / supported_m as u64]); + + assert!( + omega_0.pow_vartime(&[supported_n as u64]) == E::Fr::ONE, + "omega_0 is not root of unity for supported_n" + ); + assert!( + omega_1.pow_vartime(&[supported_m as u64]) == E::Fr::ONE, + "omega_1 is not root of unity for supported_m" + ); + (omega_0, omega_1) + }; + + // println!("start to compute the scalars"); + // computes the vector of L_i^N(tau_0) * L_j^M(tau_1) for i in 0..supported_n and j in 0..supported_m + let (scalars, lagrange_scalars) = { + let powers_of_omega_0 = powers_of_field_elements(&omega_0, supported_n); + let powers_of_tau_0 = powers_of_field_elements(&tau_0, supported_n); + let lagrange_tau_0 = lagrange_coefficients(&powers_of_omega_0, &tau_0); + let powers_of_omega_1 = powers_of_field_elements(&omega_1, supported_m); + let powers_of_tau_1 = powers_of_field_elements(&tau_1, supported_m); + let lagrange_tau_1 = lagrange_coefficients(&powers_of_omega_1, &tau_1); + let scalars = tensor_product_parallel(&powers_of_tau_0, &powers_of_tau_1); + let lagrange_scalars = tensor_product_parallel(&lagrange_tau_0, &lagrange_tau_1); + + (scalars, lagrange_scalars) + }; + + // println!("start to compute the affine bases"); + let g1_prog = g1.to_curve(); + let coeff_bases = { + let mut proj_bases = vec![E::G1::identity(); supported_n * supported_m]; + parallelize(&mut proj_bases, |g, start| { + for (idx, g) in g.iter_mut().enumerate() { + let offset = start + idx; + *g = g1_prog * scalars[offset]; + } + }); + + let mut g_bases = vec![E::G1Affine::identity(); supported_n * supported_m]; + parallelize(&mut g_bases, |g, starts| { + E::G1::batch_normalize(&proj_bases[starts..(starts + g.len())], g); + }); + drop(proj_bases); + g_bases + }; + + // println!("start to compute the lagrange bases"); + + let lagrange_bases = { + let mut proj_bases = vec![E::G1::identity(); supported_n * supported_m]; + parallelize(&mut proj_bases, |g, start| { + for (idx, g) in g.iter_mut().enumerate() { + let offset = start + idx; + *g = g1 * lagrange_scalars[offset]; + } + }); + + let mut affine_bases = vec![E::G1Affine::identity(); supported_n * supported_m]; + parallelize(&mut affine_bases, |affine_bases, starts| { + E::G1::batch_normalize( + &proj_bases[starts..(starts + affine_bases.len())], + affine_bases, + ); + }); + drop(proj_bases); + affine_bases + }; + + // assert_eq!(coeff_bases[..supported_n], f_x_b_scalars); + + BiKZGSRS { + powers_of_g: coeff_bases, + powers_of_g_lagrange_over_both_roots: lagrange_bases, + h: E::G2Affine::generator(), + tau_0_h: (E::G2Affine::generator() * tau_0).into(), + tau_1_h: (E::G2Affine::generator() * tau_1).into(), + } + } + + // fn trim( + // srs: impl Borrow, + // supported_degree: Option, + // supported_num_vars: Option, + // ) -> (Self::ProverParam, Self::VerifierParam) { + // unimplemented!() + // } + + fn commit( + prover_param: impl Borrow, + poly: &Self::Polynomial, + ) -> Self::Commitment { + let timer = start_timer!(|| format!( + "Committing to lagrange polynomial of degree {} {}", + poly.degree_0, poly.degree_1 + )); + + let com = best_multiexp( + &poly.coefficients, + prover_param + .borrow() + .powers_of_g_lagrange_over_both_roots + .as_slice(), + ); + + end_timer!(timer); + + Self::Commitment { com: com.into() } + } + + fn open( + prover_param: impl Borrow, + polynomial: &Self::Polynomial, + point: &Self::Point, + ) -> (Self::Proof, Self::Evaluation) { + let timer = start_timer!(|| format!( + "Opening polynomial of degree {} {}", + polynomial.degree_0, polynomial.degree_1 + )); + + let a = point.0; + let b = point.1; + let u = polynomial.evaluate(&a, &b); + + let timer2 = start_timer!(|| "Computing the proof pi0"); + let (pi_0, f_x_b) = { + let f_x_b = polynomial.evaluate_y(&point.1); + let mut q_0_x_b = f_x_b.clone(); + q_0_x_b[0] -= u; + let q_0_x_b = univariate_quotient(&q_0_x_b, &point.0); + + let pi_0 = best_multiexp( + &q_0_x_b, + prover_param.borrow().powers_of_g[..polynomial.degree_0].as_ref(), + ) + .to_affine(); + (pi_0, f_x_b) + }; + end_timer!(timer2); + + let timer2 = start_timer!(|| "Computing the proof pi1"); + let pi_1 = { + let mut t = polynomial.clone(); + t.coefficients + .iter_mut() + .take(polynomial.degree_0) + .zip_eq(f_x_b.iter()) + .for_each(|(c, f)| *c -= f); + let coeffs = t.lagrange_coeffs(); + + let mut divisor = vec![E::Fr::from(0); polynomial.degree_0 * polynomial.degree_1]; + divisor[0] = -point.1; + divisor[polynomial.degree_0] = E::Fr::ONE; + let divisor = + BivariatePolynomial::new(divisor, polynomial.degree_0, polynomial.degree_1); + + let divisor = divisor.lagrange_coeffs(); + + // todo: batch invert + let y_minus_a_inv_lag = divisor + .iter() + .map(|o| { + if o.is_zero_vartime() { + panic!("not invertible") + } else { + o.invert().unwrap() + } + }) + .collect::>(); + + let q_1_x_y = coeffs + .iter() + .zip_eq(y_minus_a_inv_lag.iter()) + .map(|(c, y)| (*c) * *y) + .collect::>(); + + best_multiexp( + &q_1_x_y, + prover_param + .borrow() + .powers_of_g_lagrange_over_both_roots + .as_ref(), + ) + .to_affine() + }; + end_timer!(timer2); + let proof = BiKZGProof:: { + pi0: pi_0, + pi1: pi_1, + }; + + end_timer!(timer); + (proof, u) + } + + fn verify( + verifier_param: &Self::VerifierParam, + commitment: &Self::Commitment, + point: &Self::Point, + value: &Self::Evaluation, + proof: &Self::Proof, + ) -> bool + where + E: MultiMillerLoop, + { + let pi0_a_pi1_b_g1_cmu = best_multiexp( + &[point.0, point.1, E::Fr::ONE, -*value], + &[ + proof.pi0, + proof.pi1, + commitment.com.into(), + verifier_param.g.into(), + ], + ); + let pi0_a_pi1_b_g1_cmu = (-pi0_a_pi1_b_g1_cmu).to_affine(); + let res = E::multi_miller_loop(&[ + (&proof.pi0, &verifier_param.tau_0_h.into()), + (&proof.pi1, &verifier_param.tau_1_h.into()), + (&pi0_a_pi1_b_g1_cmu, &verifier_param.h.into()), + ]); + let res = res.final_exponentiation().is_identity().into(); + + res + } + + fn multi_open( + _prover_param: impl Borrow, + _polynomials: &[Self::Polynomial], + _points: &[Self::Point], + _evals: &[Self::Evaluation], + ) -> Self::BatchProof { + unimplemented!() + } + + fn batch_verify( + _verifier_param: &Self::VerifierParam, + _commitments: &[Self::Commitment], + _points: &[Self::Point], + _batch_proof: &Self::BatchProof, + ) -> bool { + unimplemented!() + } +} diff --git a/bi-kzg/src/lib.rs b/bi-kzg/src/lib.rs index 0600a294..96079f99 100644 --- a/bi-kzg/src/lib.rs +++ b/bi-kzg/src/lib.rs @@ -1,13 +1,16 @@ -mod bi_kzg; -mod msm; +mod bi_fft; +mod coeff_form_bi_kzg; +// mod lagrange_form_bi_kzg; mod pcs; mod poly; mod structs; +mod util; + #[cfg(test)] mod tests; -mod util; -pub use bi_kzg::BiKZG; +pub use coeff_form_bi_kzg::CoeffFormBiKZG; +// pub use lagrange_form_bi_kzg::LagrangeFormBiKZG; pub use pcs::PolynomialCommitmentScheme; pub use structs::BivariatePolynomial; pub use structs::{BiKZGCommitment, BiKZGProof, BiKZGSRS, BiKZGVerifierParam}; diff --git a/bi-kzg/src/msm.rs b/bi-kzg/src/msm.rs deleted file mode 100644 index 0769c2fd..00000000 --- a/bi-kzg/src/msm.rs +++ /dev/null @@ -1,171 +0,0 @@ -//! credit: https://github.com/zhenfeizhang/halo2curves/blob/inline/src/msm.rs -//! Code modified to simplify the implementation and remove the need for the `Curve` trait. - -use std::ops::{Add, Neg}; - -use ark_std::{end_timer, start_timer}; -use halo2curves::ff::PrimeField; -use halo2curves::group::Group; -use halo2curves::pairing::PairingCurveAffine; - -fn get_booth_index(window_index: usize, window_size: usize, el: &[u8]) -> i32 { - // Booth encoding: - // * step by `window` size - // * slice by size of `window + 1`` - // * each window overlap by 1 bit - // * append a zero bit to the least significant end - // Indexing rule for example window size 3 where we slice by 4 bits: - // `[0, +1, +1, +2, +2, +3, +3, +4, -4, -3, -3 -2, -2, -1, -1, 0]`` - // So we can reduce the bucket size without preprocessing scalars - // and remembering them as in classic signed digit encoding - - let skip_bits = (window_index * window_size).saturating_sub(1); - let skip_bytes = skip_bits / 8; - - // fill into a u32 - let mut v: [u8; 4] = [0; 4]; - for (dst, src) in v.iter_mut().zip(el.iter().skip(skip_bytes)) { - *dst = *src - } - let mut tmp = u32::from_le_bytes(v); - - // pad with one 0 if slicing the least significant window - if window_index == 0 { - tmp <<= 1; - } - - // remove further bits - tmp >>= skip_bits - (skip_bytes * 8); - // apply the booth window - tmp &= (1 << (window_size + 1)) - 1; - - let sign = tmp & (1 << window_size) == 0; - - // div ceil by 2 - tmp = (tmp + 1) >> 1; - - // find the booth action index - if sign { - tmp as i32 - } else { - ((!(tmp - 1) & ((1 << window_size) - 1)) as i32).neg() - } -} - -/// Performs a multi-exponentiation operation. -/// -/// This function will panic if coeffs and bases have a different length. -/// -/// This will use multithreading if beneficial. -pub fn best_multiexp>( - coeffs: &[C::Scalar], - bases: &[C], -) -> C::Curve { - let timer = start_timer!(|| format!("Multiexp of dim {}", coeffs.len())); - assert_eq!(coeffs.len(), bases.len()); - - let num_threads = rayon::current_num_threads(); - let res = if coeffs.len() > num_threads { - let chunk = coeffs.len() / num_threads; - let num_chunks = coeffs.chunks(chunk).len(); - let mut results = vec![C::Curve::identity(); num_chunks]; - rayon::scope(|scope| { - let chunk = coeffs.len() / num_threads; - - for ((coeffs, bases), acc) in coeffs - .chunks(chunk) - .zip(bases.chunks(chunk)) - .zip(results.iter_mut()) - { - scope.spawn(move |_| { - multiexp_serial(coeffs, bases, acc); - }); - } - }); - results.iter().fold(C::Curve::identity(), |a, b| a + b) - } else { - let mut acc = C::Curve::identity(); - multiexp_serial(coeffs, bases, &mut acc); - acc - }; - - end_timer!(timer); - res -} - -pub fn multiexp_serial>( - coeffs: &[C::Scalar], - bases: &[C], - acc: &mut C::Curve, -) { - let coeffs: Vec<_> = coeffs.iter().map(|a| a.to_repr()).collect(); - - let c = if bases.len() < 4 { - 1 - } else if bases.len() < 32 { - 3 - } else { - (f64::from(bases.len() as u32)).ln().ceil() as usize - }; - - let number_of_windows = C::Scalar::NUM_BITS as usize / c + 1; - - for current_window in (0..number_of_windows).rev() { - for _ in 0..c { - *acc = acc.double(); - } - - #[derive(Clone, Copy)] - enum Bucket { - None, - Affine(C), - Projective(C::Curve), - } - - impl> Bucket { - fn add_assign(&mut self, other: &C) { - *self = match *self { - Bucket::None => Bucket::Affine(*other), - Bucket::Affine(a) => Bucket::Projective(a + *other), - Bucket::Projective(mut a) => { - a += *other; - Bucket::Projective(a) - } - } - } - - fn add(self, mut other: C::Curve) -> C::Curve { - match self { - Bucket::None => other, - Bucket::Affine(a) => { - other += a; - other - } - Bucket::Projective(a) => other + a, - } - } - } - - let mut buckets: Vec> = vec![Bucket::None; 1 << (c - 1)]; - - for (coeff, base) in coeffs.iter().zip(bases.iter()) { - let coeff = get_booth_index(current_window, c, coeff.as_ref()); - if coeff.is_positive() { - buckets[coeff as usize - 1].add_assign(base); - } - if coeff.is_negative() { - buckets[coeff.unsigned_abs() as usize - 1].add_assign(&base.neg()); - } - } - - // Summation by parts - // e.g. 3a + 2b + 1c = a + - // (a) + b + - // ((a) + b) + c - let mut running_sum = C::Curve::identity(); - for exp in buckets.into_iter().rev() { - running_sum = exp.add(running_sum); - *acc += &running_sum; - } - } -} diff --git a/bi-kzg/src/tests.rs b/bi-kzg/src/tests.rs index 0c41c828..f79a9f31 100644 --- a/bi-kzg/src/tests.rs +++ b/bi-kzg/src/tests.rs @@ -5,8 +5,9 @@ use halo2curves::{ }; use crate::{ - bi_kzg::BiKZG, pcs::PolynomialCommitmentScheme, poly::lagrange_coefficients, - util::tensor_product_parallel, BiKZGVerifierParam, BivariatePolynomial, + coeff_form_bi_kzg::CoeffFormBiKZG, pcs::PolynomialCommitmentScheme, + poly::lagrange_coefficients, util::tensor_product_parallel, BiKZGVerifierParam, + BivariatePolynomial, }; #[test] @@ -15,7 +16,7 @@ fn test_bi_kzg_with_profiling() { let n = 16; let m = 32; - let srs = BiKZG::::gen_srs_for_testing(&mut rng, n, m); + let srs = CoeffFormBiKZG::::gen_srs_for_testing(&mut rng, n, m); let vk = BiKZGVerifierParam::::from(&srs); let poly = BivariatePolynomial::::random(&mut rng, n, m); @@ -23,9 +24,15 @@ fn test_bi_kzg_with_profiling() { let x = Fr::random(&mut rng); let y = Fr::random(&mut rng); - let commit = BiKZG::::commit(&srs, &poly); - let (proof, eval) = BiKZG::::open(&srs, &poly, &(x, y)); - assert!(BiKZG::::verify(&vk, &commit, &(x, y), &eval, &proof)); + let commit = CoeffFormBiKZG::::commit(&srs, &poly); + let (proof, eval) = CoeffFormBiKZG::::open(&srs, &poly, &(x, y)); + assert!(CoeffFormBiKZG::::verify( + &vk, + &commit, + &(x, y), + &eval, + &proof + )); } #[test] @@ -33,7 +40,7 @@ fn test_bi_kzg_e2e() { let mut rng = test_rng(); let n = 2; let m = 4; - let srs = BiKZG::::gen_srs_for_testing(&mut rng, n, m); + let srs = CoeffFormBiKZG::::gen_srs_for_testing(&mut rng, n, m); let vk = BiKZGVerifierParam::::from(&srs); let poly = BivariatePolynomial::new( vec![ @@ -56,14 +63,20 @@ fn test_bi_kzg_e2e() { assert_eq!(poly.evaluate(&x, &y), Fr::from(85309u64)); - let commit = BiKZG::::commit(&srs, &poly); - let (proof, eval) = BiKZG::::open(&srs, &poly, &(x, y)); + let commit = CoeffFormBiKZG::::commit(&srs, &poly); + let (proof, eval) = CoeffFormBiKZG::::open(&srs, &poly, &(x, y)); - assert!(BiKZG::::verify(&vk, &commit, &(x, y), &eval, &proof)); + assert!(CoeffFormBiKZG::::verify( + &vk, + &commit, + &(x, y), + &eval, + &proof + )); for n in [2, 4, 8, 16] { for m in [2, 4, 8, 16] { - let srs = BiKZG::::gen_srs_for_testing(&mut rng, n, m); + let srs = CoeffFormBiKZG::::gen_srs_for_testing(&mut rng, n, m); let vk = BiKZGVerifierParam::::from(&srs); for _ in 0..10 { let poly = BivariatePolynomial::::random(&mut rng, n, m); @@ -71,9 +84,15 @@ fn test_bi_kzg_e2e() { let x = Fr::random(&mut rng); let y = Fr::random(&mut rng); - let commit = BiKZG::::commit(&srs, &poly); - let (proof, eval) = BiKZG::::open(&srs, &poly, &(x, y)); - assert!(BiKZG::::verify(&vk, &commit, &(x, y), &eval, &proof)); + let commit = CoeffFormBiKZG::::commit(&srs, &poly); + let (proof, eval) = CoeffFormBiKZG::::open(&srs, &poly, &(x, y)); + assert!(CoeffFormBiKZG::::verify( + &vk, + &commit, + &(x, y), + &eval, + &proof + )); } } } From 7da6a48cac5b112efdbfd4a46baeb2d8a62aa3a6 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Tue, 18 Jun 2024 15:34:04 -0400 Subject: [PATCH 25/31] bi-fft single thread done --- bi-kzg/src/bi_fft.rs | 246 ++++++++++++++++++++++++++++++++ bi-kzg/src/coeff_form_bi_kzg.rs | 6 +- 2 files changed, 251 insertions(+), 1 deletion(-) diff --git a/bi-kzg/src/bi_fft.rs b/bi-kzg/src/bi_fft.rs index d20697ac..0087cb51 100644 --- a/bi-kzg/src/bi_fft.rs +++ b/bi-kzg/src/bi_fft.rs @@ -1 +1,247 @@ //! Two layer FFT and its inverse + +use ark_std::log2; +use halo2curves::{ + ff::{Field, PrimeField}, + fft::{best_fft, FftGroup}, +}; + +// #[inline] +// fn swap_chunks(a: &mut [&mut[F]], rk: usize, k: usize) { + +// a.swap( rk, k); + +// } + +fn assign_vec(a: &mut [F], b: &[F], n: usize) { + assert!(a.len() == n); + assert!(b.len() == n); + a.iter_mut() + .zip(b.iter()) + .take(n) + .for_each(|(a, b)| *a = *b); +} + +#[inline] +fn add_assign_vec(a: &mut [F], b: &[F], n: usize) { + assert!(a.len() == n); + assert!(b.len() == n); + + a.iter_mut() + .zip(b.iter()) + .take(n) + .for_each(|(a, b)| *a += b); +} + +#[inline] +fn sub_assign_vec(a: &mut [F], b: &[F], n: usize) { + assert!(a.len() == n); + assert!(b.len() == n); + a.iter_mut() + .zip(b.iter()) + .take(n) + .for_each(|(a, b)| *a -= b); +} + +#[inline] +fn mul_assign_vec(a: &mut [F], b: &F, n: usize) { + assert!(a.len() == n); + a.iter_mut().take(n).for_each(|a| *a *= b); +} + +// code copied from Halo2curves with adaption to vectors +// + +/// Performs a radix-$2$ Fast-Fourier Transformation (FFT) on a vector of size +/// $n = 2^k$, when provided `log_n` = $k$ and an element of multiplicative +/// order $n$ called `omega` ($\omega$). The result is that the vector `a`, when +/// interpreted as the coefficients of a polynomial of degree $n - 1$, is +/// transformed into the evaluations of this polynomial at each of the $n$ +/// distinct powers of $\omega$. This transformation is invertible by providing +/// $\omega^{-1}$ in place of $\omega$ and dividing each resulting field element +/// by $n$. +/// +/// This will use multithreading if beneficial. +pub fn best_fft_vec(a: &mut [F], omega: F, log_n: u32, log_m: u32) { + fn bitreverse(mut n: usize, l: usize) -> usize { + let mut r = 0; + for _ in 0..l { + r = (r << 1) | (n & 1); + n >>= 1; + } + r + } + + let threads = rayon::current_num_threads(); + let log_threads = threads.ilog2(); + let mn = a.len(); + let m = 1 << log_m; + let n = 1 << log_n; + assert_eq!(mn, 1 << (log_n + log_m)); + + let mut a_vec_ptrs = a.chunks_exact_mut(n).collect::>(); + + for k in 0..m { + let rk = bitreverse(k, log_m as usize); + if k < rk { + a_vec_ptrs.swap(rk, k); + } + } + + // precompute twiddle factors + let twiddles: Vec<_> = (0..(m / 2)) + .scan(F::ONE, |w, _| { + let tw = *w; + *w *= ω + Some(tw) + }) + .collect(); + + // if log_n <= log_threads { + let mut chunk = 2_usize; + let mut twiddle_chunk = m / 2; + for _ in 0..log_m { + a_vec_ptrs.chunks_mut(chunk).for_each(|coeffs| { + let (left, right) = coeffs.split_at_mut(chunk / 2); + + // case when twiddle factor is one + let (a, left) = left.split_at_mut(1); + let (b, right) = right.split_at_mut(1); + let t = b[0].to_vec(); + + // b[0] = a[0]; + // a[0] += &t; + // b[0] -= &t; + assign_vec(b[0], a[0], n); + add_assign_vec(a[0], &t, n); + sub_assign_vec(b[0], &t, n); + + left.iter_mut() + .zip(right.iter_mut()) + .enumerate() + .for_each(|(i, (a, b))| { + let mut t = b.to_vec(); + + // t *= &twiddles[(i + 1) * twiddle_chunk]; + // *b = *a; + // *a += &t; + // *b -= &t; + + mul_assign_vec(&mut t, &twiddles[(i + 1) * twiddle_chunk], n); + assign_vec(b, a, n); + add_assign_vec(a, &t, n); + sub_assign_vec(b, &t, n); + }); + }); + chunk *= 2; + twiddle_chunk /= 2; + } + // } else { + // recursive_butterfly_arithmetic(a, n, 1, &twiddles) + // } +} + +// /// This perform recursive butterfly arithmetic +// pub fn recursive_butterfly_arithmetic>( +// a: &mut [G], +// n: usize, +// twiddle_chunk: usize, +// twiddles: &[Scalar], +// ) { +// if n == 2 { +// let t = a[1]; +// a[1] = a[0]; +// a[0] += &t; +// a[1] -= &t; +// } else { +// let (left, right) = a.split_at_mut(n / 2); +// rayon::join( +// || recursive_butterfly_arithmetic(left, n / 2, twiddle_chunk * 2, twiddles), +// || recursive_butterfly_arithmetic(right, n / 2, twiddle_chunk * 2, twiddles), +// ); + +// // case when twiddle factor is one +// let (a, left) = left.split_at_mut(1); +// let (b, right) = right.split_at_mut(1); +// let t = b[0]; +// b[0] = a[0]; +// a[0] += &t; +// b[0] -= &t; + +// left.iter_mut() +// .zip(right.iter_mut()) +// .enumerate() +// .for_each(|(i, (a, b))| { +// let mut t = *b; +// t *= &twiddles[(i + 1) * twiddle_chunk]; +// *b = *a; +// *a += &t; +// *b -= &t; +// }); +// } +// } + +pub(crate) fn bi_fft_in_place(coeffs: &mut [F], degree_n: usize, degree_m: usize) { + // roots of unity for supported_n and supported_m + let (omega_0, omega_1) = { + let omega = F::ROOT_OF_UNITY; + let omega_0 = omega.pow_vartime(&[(1 << F::S) / degree_n as u64]); + let omega_1 = omega.pow_vartime(&[(1 << F::S) / degree_m as u64]); + + assert!( + omega_0.pow_vartime(&[degree_n as u64]) == F::ONE, + "omega_0 is not root of unity for supported_n" + ); + assert!( + omega_1.pow_vartime(&[degree_m as u64]) == F::ONE, + "omega_1 is not root of unity for supported_m" + ); + (omega_0, omega_1) + }; + + coeffs + .chunks_exact_mut(degree_n) + .for_each(|chunk| best_fft(chunk, omega_0, log2(degree_n))); + + println!("before: {:?}", coeffs); + best_fft_vec(coeffs, omega_1, log2(degree_n), log2(degree_m)); + println!("after: {:?}", coeffs); +} + +#[cfg(test)] +mod tests { + use ark_std::test_rng; + use halo2curves::bn256::Fr; + + use crate::BivariatePolynomial; + + use super::bi_fft_in_place; + + #[test] + fn test_bi_fft() { + { + let n = 2; + let m = 4; + let poly = BivariatePolynomial::new( + vec![ + Fr::from(1u64), + Fr::from(2u64), + Fr::from(3u64), + Fr::from(4u64), + Fr::from(5u64), + Fr::from(6u64), + Fr::from(7u64), + Fr::from(8u64), + ], + n, + m, + ); + let mut poly_lag2 = poly.coefficients.clone(); + let poly_lag = poly.lagrange_coeffs(); + bi_fft_in_place(&mut poly_lag2, n, m); + assert_eq!(poly_lag, poly_lag2); + } + + let mut rng = test_rng(); + } +} diff --git a/bi-kzg/src/coeff_form_bi_kzg.rs b/bi-kzg/src/coeff_form_bi_kzg.rs index ecd4a85b..f32e0e15 100644 --- a/bi-kzg/src/coeff_form_bi_kzg.rs +++ b/bi-kzg/src/coeff_form_bi_kzg.rs @@ -43,7 +43,11 @@ where type Point = (E::Fr, E::Fr); type BatchProof = Vec; - fn gen_srs_for_testing(mut rng: impl RngCore, supported_n: usize, supported_m: usize) -> Self::SRS { + fn gen_srs_for_testing( + mut rng: impl RngCore, + supported_n: usize, + supported_m: usize, + ) -> Self::SRS { // LagrangeFormBiKZG::::gen_srs_for_testing(rng, supported_n, supported_m) assert!(supported_n.is_power_of_two()); From aa890854901d53c1e44038fad6b399fa70785195 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Tue, 18 Jun 2024 16:44:22 -0400 Subject: [PATCH 26/31] fix bug in bi-fft --- bi-kzg/src/bi_fft.rs | 133 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 113 insertions(+), 20 deletions(-) diff --git a/bi-kzg/src/bi_fft.rs b/bi-kzg/src/bi_fft.rs index 0087cb51..441249b7 100644 --- a/bi-kzg/src/bi_fft.rs +++ b/bi-kzg/src/bi_fft.rs @@ -6,10 +6,36 @@ use halo2curves::{ fft::{best_fft, FftGroup}, }; +fn bitreverse(mut n: usize, l: usize) -> usize { + let mut r = 0; + for _ in 0..l { + r = (r << 1) | (n & 1); + n >>= 1; + } + r +} + +#[inline] +fn deep_swap_chunks(a: &mut [&mut [F]], rk: usize, k: usize) { + let buf1 = (a[k]).to_vec(); + let buf2 = (a[rk]).to_vec(); + a[rk].copy_from_slice(&buf1); + a[k].copy_from_slice(&buf2); + // a[rk].iter_mut().zip(a[k].iter_mut()).for_each(|(a, b)| { + // let t = *a; + // *a = *b; + // *b = t}); +} + // #[inline] -// fn swap_chunks(a: &mut [&mut[F]], rk: usize, k: usize) { +// fn swap_chunks(a: &mut [F], log_n: u32) { -// a.swap( rk, k); +// for k in 0..1<(a: &mut [F], b: &F, n: usize) { /// by $n$. /// /// This will use multithreading if beneficial. -pub fn best_fft_vec(a: &mut [F], omega: F, log_n: u32, log_m: u32) { - fn bitreverse(mut n: usize, l: usize) -> usize { - let mut r = 0; - for _ in 0..l { - r = (r << 1) | (n & 1); - n >>= 1; - } - r - } - +pub fn best_fft_vec(a: &mut [F], omega: F, log_n: u32, log_m: u32) { let threads = rayon::current_num_threads(); let log_threads = threads.ilog2(); let mn = a.len(); @@ -79,12 +96,36 @@ pub fn best_fft_vec(a: &mut [F], omega: F, log_n: u32, log_m: u32) { let n = 1 << log_n; assert_eq!(mn, 1 << (log_n + log_m)); + // let mut a = (0..mn).map(|i| F::from(i as u64)).collect::>(); + // println!("a: {:?}", a); + // swap_chunks(a, log_n+log_m); + // println!("a: {:?}", a); let mut a_vec_ptrs = a.chunks_exact_mut(n).collect::>(); + // for a in a_vec_ptrs.iter_mut() { + // swap_chunks(a, log_n); + // } + for k in 0..m { let rk = bitreverse(k, log_m as usize); + if k < rk { - a_vec_ptrs.swap(rk, k); + println!("k: {}, rk: {}", k, rk); + for a in a_vec_ptrs.iter().enumerate() { + println!("{}: {:?}", a.0, a.1); + } + + deep_swap_chunks(&mut a_vec_ptrs, rk, k ); + + // a_vec_ptrs.swap(rk, k); + // swap_chunks(a_vec_ptrs[k], log_n); + // swap_chunks(a_vec_ptrs[rk], log_n); + + for a in a_vec_ptrs.iter().enumerate() { + println!("{}: {:?}", a.0, a.1); + } + + println!(); } } @@ -136,9 +177,33 @@ pub fn best_fft_vec(a: &mut [F], omega: F, log_n: u32, log_m: u32) { chunk *= 2; twiddle_chunk /= 2; } - // } else { - // recursive_butterfly_arithmetic(a, n, 1, &twiddles) + // // } else { + // // recursive_butterfly_arithmetic(a, n, 1, &twiddles) + // // } + // println!("before is correct: {:?}", a_vec_ptrs); + + // for k in 0..m { + // let rk = bitreverse(k, log_m as usize); + + // if k < rk { + // println!("k: {}, rk: {}", k, rk); + // for a in a_vec_ptrs.iter().enumerate() { + // println!("{}: {:?}", a.0, a.1); + // } + + // a_vec_ptrs.swap(rk, k); + // // swap_chunks(a_vec_ptrs[k], log_n); + // // swap_chunks(a_vec_ptrs[rk], log_n); + + // for a in a_vec_ptrs.iter().enumerate() { + // println!("{}: {:?}", a.0, a.1); + // } + + // println!(); + // } // } + + // println!("after: {:?}", a_vec_ptrs); } // /// This perform recursive butterfly arithmetic @@ -220,18 +285,26 @@ mod tests { #[test] fn test_bi_fft() { { - let n = 2; + let n = 4; let m = 4; let poly = BivariatePolynomial::new( vec![ Fr::from(1u64), Fr::from(2u64), - Fr::from(3u64), Fr::from(4u64), - Fr::from(5u64), - Fr::from(6u64), - Fr::from(7u64), Fr::from(8u64), + Fr::from(16u64), + Fr::from(32u64), + Fr::from(64u64), + Fr::from(128u64), + Fr::from(256u64), + Fr::from(128u64), + Fr::from(64u64), + Fr::from(32u64), + Fr::from(16u64), + Fr::from(8u64), + Fr::from(4u64), + Fr::from(2u64), ], n, m, @@ -239,9 +312,29 @@ mod tests { let mut poly_lag2 = poly.coefficients.clone(); let poly_lag = poly.lagrange_coeffs(); bi_fft_in_place(&mut poly_lag2, n, m); + + for (i, (a, b)) in poly_lag.iter().zip(poly_lag2.iter()).enumerate() { + println!("{}: {:?} == {:?}", i, a, b); + } + + println!("correct one {:?}", poly_lag); + // println!(); + // println!("{:?}", poly_lag2); + // println!(); assert_eq!(poly_lag, poly_lag2); } let mut rng = test_rng(); + + for m in [2, 4, 8, 16].iter() { + for n in [2, 4, 8, 16].iter() { + let poly = BivariatePolynomial::::random(&mut rng, *n, *m); + let mut poly_lag2 = poly.coefficients.clone(); + let poly_lag = poly.lagrange_coeffs(); + bi_fft_in_place(&mut poly_lag2, *n, *m); + println!("m = {}, n = {}: {}", m, n, poly_lag == poly_lag2); + assert_eq!(poly_lag, poly_lag2); + } + } } } From 2d4c6c90069a6e8fcb4d3c55a254c2fdf6e6532a Mon Sep 17 00:00:00 2001 From: zhenfei Date: Tue, 18 Jun 2024 16:54:09 -0400 Subject: [PATCH 27/31] clean up --- bi-kzg/src/bi_fft.rs | 38 +++++++++++++++------------------ bi-kzg/src/coeff_form_bi_kzg.rs | 14 ++++++++---- bi-kzg/src/poly.rs | 5 +++++ 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/bi-kzg/src/bi_fft.rs b/bi-kzg/src/bi_fft.rs index 441249b7..d55db451 100644 --- a/bi-kzg/src/bi_fft.rs +++ b/bi-kzg/src/bi_fft.rs @@ -3,7 +3,7 @@ use ark_std::log2; use halo2curves::{ ff::{Field, PrimeField}, - fft::{best_fft, FftGroup}, + fft::best_fft, }; fn bitreverse(mut n: usize, l: usize) -> usize { @@ -21,10 +21,6 @@ fn deep_swap_chunks(a: &mut [&mut [F]], rk: usize, k: usize) { let buf2 = (a[rk]).to_vec(); a[rk].copy_from_slice(&buf1); a[k].copy_from_slice(&buf2); - // a[rk].iter_mut().zip(a[k].iter_mut()).for_each(|(a, b)| { - // let t = *a; - // *a = *b; - // *b = t}); } // #[inline] @@ -110,22 +106,22 @@ pub fn best_fft_vec(a: &mut [F], omega: F, log_n: u32, log_m: u32 let rk = bitreverse(k, log_m as usize); if k < rk { - println!("k: {}, rk: {}", k, rk); - for a in a_vec_ptrs.iter().enumerate() { - println!("{}: {:?}", a.0, a.1); - } + // println!("k: {}, rk: {}", k, rk); + // for a in a_vec_ptrs.iter().enumerate() { + // println!("{}: {:?}", a.0, a.1); + // } - deep_swap_chunks(&mut a_vec_ptrs, rk, k ); + deep_swap_chunks(&mut a_vec_ptrs, rk, k); // a_vec_ptrs.swap(rk, k); // swap_chunks(a_vec_ptrs[k], log_n); // swap_chunks(a_vec_ptrs[rk], log_n); - for a in a_vec_ptrs.iter().enumerate() { - println!("{}: {:?}", a.0, a.1); - } + // for a in a_vec_ptrs.iter().enumerate() { + // println!("{}: {:?}", a.0, a.1); + // } - println!(); + // println!(); } } @@ -268,9 +264,9 @@ pub(crate) fn bi_fft_in_place(coeffs: &mut [F], degree_n: usize, .chunks_exact_mut(degree_n) .for_each(|chunk| best_fft(chunk, omega_0, log2(degree_n))); - println!("before: {:?}", coeffs); + // println!("before: {:?}", coeffs); best_fft_vec(coeffs, omega_1, log2(degree_n), log2(degree_m)); - println!("after: {:?}", coeffs); + // println!("after: {:?}", coeffs); } #[cfg(test)] @@ -313,11 +309,11 @@ mod tests { let poly_lag = poly.lagrange_coeffs(); bi_fft_in_place(&mut poly_lag2, n, m); - for (i, (a, b)) in poly_lag.iter().zip(poly_lag2.iter()).enumerate() { - println!("{}: {:?} == {:?}", i, a, b); - } + // for (i, (a, b)) in poly_lag.iter().zip(poly_lag2.iter()).enumerate() { + // println!("{}: {:?} == {:?}", i, a, b); + // } - println!("correct one {:?}", poly_lag); + // println!("correct one {:?}", poly_lag); // println!(); // println!("{:?}", poly_lag2); // println!(); @@ -332,7 +328,7 @@ mod tests { let mut poly_lag2 = poly.coefficients.clone(); let poly_lag = poly.lagrange_coeffs(); bi_fft_in_place(&mut poly_lag2, *n, *m); - println!("m = {}, n = {}: {}", m, n, poly_lag == poly_lag2); + // println!("m = {}, n = {}: {}", m, n, poly_lag == poly_lag2); assert_eq!(poly_lag, poly_lag2); } } diff --git a/bi-kzg/src/coeff_form_bi_kzg.rs b/bi-kzg/src/coeff_form_bi_kzg.rs index f32e0e15..8f988f16 100644 --- a/bi-kzg/src/coeff_form_bi_kzg.rs +++ b/bi-kzg/src/coeff_form_bi_kzg.rs @@ -160,12 +160,13 @@ where "Committing to polynomial of degree {} {}", poly.degree_0, poly.degree_1 )); - + let timer2 = + start_timer!(|| format!("Computing the msm for size {}", poly.coefficients.len())); let com = best_multiexp( &poly.coefficients, prover_param.borrow().powers_of_g.as_slice(), ); - + end_timer!(timer2); end_timer!(timer); Self::Commitment { com: com.into() } @@ -192,11 +193,13 @@ where q_0_x_b[0] -= u; let q_0_x_b = univariate_quotient(&q_0_x_b, &point.0); + let timer2 = start_timer!(|| format!("Computing the msm for size {}", q_0_x_b.len())); let pi_0 = best_multiexp( &q_0_x_b, prover_param.borrow().powers_of_g[..polynomial.degree_0].as_ref(), ) .to_affine(); + end_timer!(timer2); (pi_0, f_x_b) }; end_timer!(timer2); @@ -237,14 +240,17 @@ where .map(|(c, y)| (*c) * *y) .collect::>(); - best_multiexp( + let timer2 = start_timer!(|| format!("Computing the msm for size {}", q_1_x_y.len())); + let res = best_multiexp( &q_1_x_y, prover_param .borrow() .powers_of_g_lagrange_over_both_roots .as_ref(), ) - .to_affine() + .to_affine(); + end_timer!(timer2); + res }; end_timer!(timer2); let proof = BiKZGProof:: { diff --git a/bi-kzg/src/poly.rs b/bi-kzg/src/poly.rs index 7f3f3909..433113aa 100644 --- a/bi-kzg/src/poly.rs +++ b/bi-kzg/src/poly.rs @@ -4,6 +4,7 @@ use itertools::Itertools; use rand::RngCore; use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; +use crate::bi_fft::bi_fft_in_place; use crate::structs::{BivariateLagrangePolynomial, BivariatePolynomial}; use crate::util::powers_of_field_elements; @@ -66,6 +67,9 @@ impl BivariatePolynomial { self.degree_0, self.degree_1 )); + // let mut coeff = self.coefficients.clone(); + // bi_fft_in_place(&mut coeff, self.degree_0, self.degree_1); + // roots of unity for supported_n and supported_m let (omega_0, omega_1) = { let omega = F::ROOT_OF_UNITY; @@ -93,6 +97,7 @@ impl BivariatePolynomial { } } end_timer!(timer); + // coeff res } } From ba69d147e3b2dc01c55e17d687856e0a534bfd5c Mon Sep 17 00:00:00 2001 From: zhenfei Date: Tue, 18 Jun 2024 18:07:46 -0400 Subject: [PATCH 28/31] wip --- bi-kzg/src/bi_fft.rs | 94 ++++++++------------------------- bi-kzg/src/coeff_form_bi_kzg.rs | 4 +- bi-kzg/src/poly.rs | 41 +++----------- 3 files changed, 32 insertions(+), 107 deletions(-) diff --git a/bi-kzg/src/bi_fft.rs b/bi-kzg/src/bi_fft.rs index d55db451..576c7116 100644 --- a/bi-kzg/src/bi_fft.rs +++ b/bi-kzg/src/bi_fft.rs @@ -6,6 +6,7 @@ use halo2curves::{ fft::best_fft, }; +#[inline] fn bitreverse(mut n: usize, l: usize) -> usize { let mut r = 0; for _ in 0..l { @@ -17,63 +18,36 @@ fn bitreverse(mut n: usize, l: usize) -> usize { #[inline] fn deep_swap_chunks(a: &mut [&mut [F]], rk: usize, k: usize) { + // hmmm maybe use unsafe functions to avoid two clones here? let buf1 = (a[k]).to_vec(); let buf2 = (a[rk]).to_vec(); a[rk].copy_from_slice(&buf1); a[k].copy_from_slice(&buf2); } -// #[inline] -// fn swap_chunks(a: &mut [F], log_n: u32) { - -// for k in 0..1<(a: &mut [F], b: &[F], n: usize) { - assert!(a.len() == n); - assert!(b.len() == n); - a.iter_mut() - .zip(b.iter()) - .take(n) - .for_each(|(a, b)| *a = *b); +fn assign_vec(a: &mut [F], b: &[F]) { + a.iter_mut().zip(b.iter()).for_each(|(a, b)| *a = *b); } #[inline] -fn add_assign_vec(a: &mut [F], b: &[F], n: usize) { - assert!(a.len() == n); - assert!(b.len() == n); - - a.iter_mut() - .zip(b.iter()) - .take(n) - .for_each(|(a, b)| *a += b); +fn add_assign_vec(a: &mut [F], b: &[F]) { + a.iter_mut().zip(b.iter()).for_each(|(a, b)| *a += b); } #[inline] -fn sub_assign_vec(a: &mut [F], b: &[F], n: usize) { - assert!(a.len() == n); - assert!(b.len() == n); - a.iter_mut() - .zip(b.iter()) - .take(n) - .for_each(|(a, b)| *a -= b); +fn sub_assign_vec(a: &mut [F], b: &[F]) { + a.iter_mut().zip(b.iter()).for_each(|(a, b)| *a -= b); } #[inline] -fn mul_assign_vec(a: &mut [F], b: &F, n: usize) { - assert!(a.len() == n); - a.iter_mut().take(n).for_each(|a| *a *= b); +fn mul_assign_vec(a: &mut [F], b: &F) { + a.iter_mut().for_each(|a| *a *= b); } // code copied from Halo2curves with adaption to vectors +// todo: add multi-threading +// // - /// Performs a radix-$2$ Fast-Fourier Transformation (FFT) on a vector of size /// $n = 2^k$, when provided `log_n` = $k$ and an element of multiplicative /// order $n$ called `omega` ($\omega$). The result is that the vector `a`, when @@ -86,42 +60,20 @@ fn mul_assign_vec(a: &mut [F], b: &F, n: usize) { /// This will use multithreading if beneficial. pub fn best_fft_vec(a: &mut [F], omega: F, log_n: u32, log_m: u32) { let threads = rayon::current_num_threads(); - let log_threads = threads.ilog2(); + let _log_threads = threads.ilog2(); let mn = a.len(); let m = 1 << log_m; let n = 1 << log_n; assert_eq!(mn, 1 << (log_n + log_m)); - // let mut a = (0..mn).map(|i| F::from(i as u64)).collect::>(); - // println!("a: {:?}", a); - // swap_chunks(a, log_n+log_m); - // println!("a: {:?}", a); let mut a_vec_ptrs = a.chunks_exact_mut(n).collect::>(); - // for a in a_vec_ptrs.iter_mut() { - // swap_chunks(a, log_n); - // } - for k in 0..m { let rk = bitreverse(k, log_m as usize); if k < rk { - // println!("k: {}, rk: {}", k, rk); - // for a in a_vec_ptrs.iter().enumerate() { - // println!("{}: {:?}", a.0, a.1); - // } - + // `a_vec_ptrs.swap(rk, k)` doesn't work here as it only swaps the pointers not the actual data deep_swap_chunks(&mut a_vec_ptrs, rk, k); - - // a_vec_ptrs.swap(rk, k); - // swap_chunks(a_vec_ptrs[k], log_n); - // swap_chunks(a_vec_ptrs[rk], log_n); - - // for a in a_vec_ptrs.iter().enumerate() { - // println!("{}: {:?}", a.0, a.1); - // } - - // println!(); } } @@ -149,9 +101,9 @@ pub fn best_fft_vec(a: &mut [F], omega: F, log_n: u32, log_m: u32 // b[0] = a[0]; // a[0] += &t; // b[0] -= &t; - assign_vec(b[0], a[0], n); - add_assign_vec(a[0], &t, n); - sub_assign_vec(b[0], &t, n); + assign_vec(b[0], a[0]); + add_assign_vec(a[0], &t); + sub_assign_vec(b[0], &t); left.iter_mut() .zip(right.iter_mut()) @@ -164,10 +116,10 @@ pub fn best_fft_vec(a: &mut [F], omega: F, log_n: u32, log_m: u32 // *a += &t; // *b -= &t; - mul_assign_vec(&mut t, &twiddles[(i + 1) * twiddle_chunk], n); - assign_vec(b, a, n); - add_assign_vec(a, &t, n); - sub_assign_vec(b, &t, n); + mul_assign_vec(&mut t, &twiddles[(i + 1) * twiddle_chunk]); + assign_vec(b, a); + add_assign_vec(a, &t); + sub_assign_vec(b, &t); }); }); chunk *= 2; @@ -306,7 +258,7 @@ mod tests { m, ); let mut poly_lag2 = poly.coefficients.clone(); - let poly_lag = poly.lagrange_coeffs(); + let poly_lag = poly.interpolate(); bi_fft_in_place(&mut poly_lag2, n, m); // for (i, (a, b)) in poly_lag.iter().zip(poly_lag2.iter()).enumerate() { @@ -326,7 +278,7 @@ mod tests { for n in [2, 4, 8, 16].iter() { let poly = BivariatePolynomial::::random(&mut rng, *n, *m); let mut poly_lag2 = poly.coefficients.clone(); - let poly_lag = poly.lagrange_coeffs(); + let poly_lag = poly.interpolate(); bi_fft_in_place(&mut poly_lag2, *n, *m); // println!("m = {}, n = {}: {}", m, n, poly_lag == poly_lag2); assert_eq!(poly_lag, poly_lag2); diff --git a/bi-kzg/src/coeff_form_bi_kzg.rs b/bi-kzg/src/coeff_form_bi_kzg.rs index 8f988f16..43eb8a19 100644 --- a/bi-kzg/src/coeff_form_bi_kzg.rs +++ b/bi-kzg/src/coeff_form_bi_kzg.rs @@ -212,7 +212,7 @@ where .take(polynomial.degree_0) .zip_eq(f_x_b.iter()) .for_each(|(c, f)| *c -= f); - let coeffs = t.lagrange_coeffs(); + let coeffs = t.interpolate(); let mut divisor = vec![E::Fr::from(0); polynomial.degree_0 * polynomial.degree_1]; divisor[0] = -point.1; @@ -220,7 +220,7 @@ where let divisor = BivariatePolynomial::new(divisor, polynomial.degree_0, polynomial.degree_1); - let divisor = divisor.lagrange_coeffs(); + let divisor = divisor.interpolate(); // todo: batch invert let y_minus_a_inv_lag = divisor diff --git a/bi-kzg/src/poly.rs b/bi-kzg/src/poly.rs index 433113aa..b5e8b206 100644 --- a/bi-kzg/src/poly.rs +++ b/bi-kzg/src/poly.rs @@ -61,44 +61,17 @@ impl BivariatePolynomial { /// // TODO: this is super slow. Implement FFT for bivariate polynomials. - pub fn lagrange_coeffs(&self) -> Vec { + pub fn interpolate(&self) -> Vec { let timer = start_timer!(|| format!( "Lagrange coefficients of degree {} {}", self.degree_0, self.degree_1 )); - // let mut coeff = self.coefficients.clone(); - // bi_fft_in_place(&mut coeff, self.degree_0, self.degree_1); - - // roots of unity for supported_n and supported_m - let (omega_0, omega_1) = { - let omega = F::ROOT_OF_UNITY; - let omega_0 = omega.pow_vartime(&[(1 << F::S) / self.degree_0 as u64]); - let omega_1 = omega.pow_vartime(&[(1 << F::S) / self.degree_1 as u64]); - - assert!( - omega_0.pow_vartime(&[self.degree_0 as u64]) == F::ONE, - "omega_0 is not root of unity for supported_n" - ); - assert!( - omega_1.pow_vartime(&[self.degree_1 as u64]) == F::ONE, - "omega_1 is not root of unity for supported_m" - ); - (omega_0, omega_1) - }; - let powers_of_omega_0 = powers_of_field_elements(&omega_0, self.degree_0); - let powers_of_omega_1 = powers_of_field_elements(&omega_1, self.degree_1); - - // Todo! Optimize me. This is not efficient. - let mut res = vec![]; - for omega_1_power in powers_of_omega_1.iter() { - for omega_0_power in powers_of_omega_0.iter() { - res.push(self.evaluate(omega_0_power, omega_1_power)); - } - } + let mut coeff = self.coefficients.clone(); + bi_fft_in_place(&mut coeff, self.degree_0, self.degree_1); end_timer!(timer); - // coeff - res + coeff + } } @@ -205,7 +178,7 @@ impl BivariateLagrangePolynomial { impl From> for BivariateLagrangePolynomial { fn from(poly: BivariatePolynomial) -> Self { - let coeffs = poly.lagrange_coeffs(); + let coeffs = poly.interpolate(); BivariateLagrangePolynomial::new(coeffs, poly.degree_0, poly.degree_1) } } @@ -399,7 +372,7 @@ mod tests { 4, ); - let lagrange_coeffs = poly.lagrange_coeffs(); + let lagrange_coeffs = poly.interpolate(); // From sage script // poly_lag_coeff = [ From 8636b2c09ce4617673bb2a28e4c84f2e17f0ab0c Mon Sep 17 00:00:00 2001 From: zhenfei Date: Tue, 18 Jun 2024 18:27:16 -0400 Subject: [PATCH 29/31] clean up --- bi-kzg/src/bi_fft.rs | 235 ++++++++++++++++++++----------------------- bi-kzg/src/poly.rs | 40 +++++++- 2 files changed, 146 insertions(+), 129 deletions(-) diff --git a/bi-kzg/src/bi_fft.rs b/bi-kzg/src/bi_fft.rs index 576c7116..19ba791b 100644 --- a/bi-kzg/src/bi_fft.rs +++ b/bi-kzg/src/bi_fft.rs @@ -18,13 +18,16 @@ fn bitreverse(mut n: usize, l: usize) -> usize { #[inline] fn deep_swap_chunks(a: &mut [&mut [F]], rk: usize, k: usize) { - // hmmm maybe use unsafe functions to avoid two clones here? - let buf1 = (a[k]).to_vec(); - let buf2 = (a[rk]).to_vec(); - a[rk].copy_from_slice(&buf1); - a[k].copy_from_slice(&buf2); + let x = a[k].as_mut_ptr(); + let y = a[rk].as_mut_ptr(); + unsafe { + for i in 0..a[k].len() { + std::ptr::swap(x.add(i), y.add(i)); + } + } } +#[inline] fn assign_vec(a: &mut [F], b: &[F]) { a.iter_mut().zip(b.iter()).for_each(|(a, b)| *a = *b); } @@ -58,9 +61,9 @@ fn mul_assign_vec(a: &mut [F], b: &F) { /// by $n$. /// /// This will use multithreading if beneficial. -pub fn best_fft_vec(a: &mut [F], omega: F, log_n: u32, log_m: u32) { +pub fn best_fft_vec_in_place(a: &mut [F], omega: F, log_n: u32, log_m: u32) { let threads = rayon::current_num_threads(); - let _log_threads = threads.ilog2(); + let log_threads = threads.ilog2(); let mn = a.len(); let m = 1 << log_m; let n = 1 << log_n; @@ -86,113 +89,105 @@ pub fn best_fft_vec(a: &mut [F], omega: F, log_n: u32, log_m: u32 }) .collect(); - // if log_n <= log_threads { - let mut chunk = 2_usize; - let mut twiddle_chunk = m / 2; - for _ in 0..log_m { - a_vec_ptrs.chunks_mut(chunk).for_each(|coeffs| { - let (left, right) = coeffs.split_at_mut(chunk / 2); - - // case when twiddle factor is one - let (a, left) = left.split_at_mut(1); - let (b, right) = right.split_at_mut(1); - let t = b[0].to_vec(); - - // b[0] = a[0]; - // a[0] += &t; - // b[0] -= &t; - assign_vec(b[0], a[0]); - add_assign_vec(a[0], &t); - sub_assign_vec(b[0], &t); - - left.iter_mut() - .zip(right.iter_mut()) - .enumerate() - .for_each(|(i, (a, b))| { - let mut t = b.to_vec(); - - // t *= &twiddles[(i + 1) * twiddle_chunk]; - // *b = *a; - // *a += &t; - // *b -= &t; - - mul_assign_vec(&mut t, &twiddles[(i + 1) * twiddle_chunk]); - assign_vec(b, a); - add_assign_vec(a, &t); - sub_assign_vec(b, &t); - }); - }); - chunk *= 2; - twiddle_chunk /= 2; + if log_n <= log_threads { + let mut chunk = 2_usize; + let mut twiddle_chunk = m / 2; + for _ in 0..log_m { + a_vec_ptrs.chunks_mut(chunk).for_each(|coeffs| { + let (left, right) = coeffs.split_at_mut(chunk / 2); + + // case when twiddle factor is one + let (a, left) = left.split_at_mut(1); + let (b, right) = right.split_at_mut(1); + let t = b[0].to_vec(); + + // compute the following in vectors + // b[0] = a[0]; + // a[0] += &t; + // b[0] -= &t; + assign_vec(b[0], a[0]); + add_assign_vec(a[0], &t); + sub_assign_vec(b[0], &t); + + left.iter_mut() + .zip(right.iter_mut()) + .enumerate() + .for_each(|(i, (a, b))| { + let mut t = b.to_vec(); + + // compute the following in vectors + // t *= &twiddles[(i + 1) * twiddle_chunk]; + // *b = *a; + // *a += &t; + // *b -= &t; + mul_assign_vec(&mut t, &twiddles[(i + 1) * twiddle_chunk]); + assign_vec(b, a); + add_assign_vec(a, &t); + sub_assign_vec(b, &t); + }); + }); + chunk *= 2; + twiddle_chunk /= 2; + } + } else { + recursive_butterfly_arithmetic(&mut a_vec_ptrs, m, n, 1, &twiddles) } - // // } else { - // // recursive_butterfly_arithmetic(a, n, 1, &twiddles) - // // } - // println!("before is correct: {:?}", a_vec_ptrs); - - // for k in 0..m { - // let rk = bitreverse(k, log_m as usize); - - // if k < rk { - // println!("k: {}, rk: {}", k, rk); - // for a in a_vec_ptrs.iter().enumerate() { - // println!("{}: {:?}", a.0, a.1); - // } - - // a_vec_ptrs.swap(rk, k); - // // swap_chunks(a_vec_ptrs[k], log_n); - // // swap_chunks(a_vec_ptrs[rk], log_n); - - // for a in a_vec_ptrs.iter().enumerate() { - // println!("{}: {:?}", a.0, a.1); - // } - - // println!(); - // } - // } - - // println!("after: {:?}", a_vec_ptrs); } -// /// This perform recursive butterfly arithmetic -// pub fn recursive_butterfly_arithmetic>( -// a: &mut [G], -// n: usize, -// twiddle_chunk: usize, -// twiddles: &[Scalar], -// ) { -// if n == 2 { -// let t = a[1]; -// a[1] = a[0]; -// a[0] += &t; -// a[1] -= &t; -// } else { -// let (left, right) = a.split_at_mut(n / 2); -// rayon::join( -// || recursive_butterfly_arithmetic(left, n / 2, twiddle_chunk * 2, twiddles), -// || recursive_butterfly_arithmetic(right, n / 2, twiddle_chunk * 2, twiddles), -// ); - -// // case when twiddle factor is one -// let (a, left) = left.split_at_mut(1); -// let (b, right) = right.split_at_mut(1); -// let t = b[0]; -// b[0] = a[0]; -// a[0] += &t; -// b[0] -= &t; +/// This perform recursive butterfly arithmetic +pub fn recursive_butterfly_arithmetic( + a: &mut [&mut [F]], + m: usize, + n: usize, + twiddle_chunk: usize, + twiddles: &[F], +) { + if m == 2 { + let t1 = a[1].to_vec(); + let t0 = a[0].to_vec(); + // compute the following in vectors + // a[1] = a[0]; + // a[0] += &t; + // a[1] -= &t; + assign_vec(a[1], &t0); + add_assign_vec(a[0], &t1); + sub_assign_vec(a[1], &t1); + } else { + let (left, right) = a.split_at_mut(m / 2); + rayon::join( + || recursive_butterfly_arithmetic(left, m / 2, n, twiddle_chunk * 2, twiddles), + || recursive_butterfly_arithmetic(right, m / 2, n, twiddle_chunk * 2, twiddles), + ); -// left.iter_mut() -// .zip(right.iter_mut()) -// .enumerate() -// .for_each(|(i, (a, b))| { -// let mut t = *b; -// t *= &twiddles[(i + 1) * twiddle_chunk]; -// *b = *a; -// *a += &t; -// *b -= &t; -// }); -// } -// } + // case when twiddle factor is one + let (a, left) = left.split_at_mut(1); + let (b, right) = right.split_at_mut(1); + let t = b[0].to_vec(); + // compute the following in vectors + // b[0] = a[0]; + // a[0] += &t; + // b[0] -= &t; + assign_vec(b[0], a[0]); + add_assign_vec(a[0], &t); + sub_assign_vec(b[0], &t); + + left.iter_mut() + .zip(right.iter_mut()) + .enumerate() + .for_each(|(i, (a, b))| { + let mut t = b.to_vec(); + // compute the following in vectors + // t *= &twiddles[(i + 1) * twiddle_chunk]; + // *b = *a; + // *a += &t; + // *b -= &t; + mul_assign_vec(&mut t, &twiddles[(i + 1) * twiddle_chunk]); + assign_vec(b, a); + add_assign_vec(a, &t); + sub_assign_vec(b, &t); + }); + } +} pub(crate) fn bi_fft_in_place(coeffs: &mut [F], degree_n: usize, degree_m: usize) { // roots of unity for supported_n and supported_m @@ -216,9 +211,7 @@ pub(crate) fn bi_fft_in_place(coeffs: &mut [F], degree_n: usize, .chunks_exact_mut(degree_n) .for_each(|chunk| best_fft(chunk, omega_0, log2(degree_n))); - // println!("before: {:?}", coeffs); - best_fft_vec(coeffs, omega_1, log2(degree_n), log2(degree_m)); - // println!("after: {:?}", coeffs); + best_fft_vec_in_place(coeffs, omega_1, log2(degree_n), log2(degree_m)); } #[cfg(test)] @@ -260,27 +253,17 @@ mod tests { let mut poly_lag2 = poly.coefficients.clone(); let poly_lag = poly.interpolate(); bi_fft_in_place(&mut poly_lag2, n, m); - - // for (i, (a, b)) in poly_lag.iter().zip(poly_lag2.iter()).enumerate() { - // println!("{}: {:?} == {:?}", i, a, b); - // } - - // println!("correct one {:?}", poly_lag); - // println!(); - // println!("{:?}", poly_lag2); - // println!(); assert_eq!(poly_lag, poly_lag2); } let mut rng = test_rng(); - for m in [2, 4, 8, 16].iter() { - for n in [2, 4, 8, 16].iter() { + for m in [2, 4, 8, 16, 32, 64].iter() { + for n in [2, 4, 8, 16, 32, 64].iter() { let poly = BivariatePolynomial::::random(&mut rng, *n, *m); let mut poly_lag2 = poly.coefficients.clone(); - let poly_lag = poly.interpolate(); + let poly_lag = poly.evaluate_at_roots(); bi_fft_in_place(&mut poly_lag2, *n, *m); - // println!("m = {}, n = {}: {}", m, n, poly_lag == poly_lag2); assert_eq!(poly_lag, poly_lag2); } } diff --git a/bi-kzg/src/poly.rs b/bi-kzg/src/poly.rs index b5e8b206..222767f7 100644 --- a/bi-kzg/src/poly.rs +++ b/bi-kzg/src/poly.rs @@ -59,8 +59,43 @@ impl BivariatePolynomial { f_x_b } - /// - // TODO: this is super slow. Implement FFT for bivariate polynomials. + /// same as interpolate but slower. + pub fn evaluate_at_roots(&self) -> Vec { + let timer = start_timer!(|| format!( + "Lagrange coefficients of degree {} {}", + self.degree_0, self.degree_1 + )); + + // roots of unity for supported_n and supported_m + let (omega_0, omega_1) = { + let omega = F::ROOT_OF_UNITY; + let omega_0 = omega.pow_vartime(&[(1 << F::S) / self.degree_0 as u64]); + let omega_1 = omega.pow_vartime(&[(1 << F::S) / self.degree_1 as u64]); + + assert!( + omega_0.pow_vartime(&[self.degree_0 as u64]) == F::ONE, + "omega_0 is not root of unity for supported_n" + ); + assert!( + omega_1.pow_vartime(&[self.degree_1 as u64]) == F::ONE, + "omega_1 is not root of unity for supported_m" + ); + (omega_0, omega_1) + }; + let powers_of_omega_0 = powers_of_field_elements(&omega_0, self.degree_0); + let powers_of_omega_1 = powers_of_field_elements(&omega_1, self.degree_1); + + let mut res = vec![]; + for omega_1_power in powers_of_omega_1.iter() { + for omega_0_power in powers_of_omega_0.iter() { + res.push(self.evaluate(omega_0_power, omega_1_power)); + } + } + end_timer!(timer); + res + } + + /// interpolate the polynomial over the roots via bi-variate FFT pub fn interpolate(&self) -> Vec { let timer = start_timer!(|| format!( "Lagrange coefficients of degree {} {}", @@ -71,7 +106,6 @@ impl BivariatePolynomial { bi_fft_in_place(&mut coeff, self.degree_0, self.degree_1); end_timer!(timer); coeff - } } From 2702817980dec172784ade130f4632149f0c0f0a Mon Sep 17 00:00:00 2001 From: zhenfei Date: Tue, 18 Jun 2024 20:28:44 -0400 Subject: [PATCH 30/31] clean up --- bi-kzg/src/bi_fft.rs | 15 ++--- bi-kzg/src/coeff_form_bi_kzg.rs | 36 +++++------ bi-kzg/src/lagrange_form_bi_kzg.rs | 9 --- bi-kzg/src/poly.rs | 97 +++++++++++++----------------- 4 files changed, 67 insertions(+), 90 deletions(-) diff --git a/bi-kzg/src/bi_fft.rs b/bi-kzg/src/bi_fft.rs index 19ba791b..acf87772 100644 --- a/bi-kzg/src/bi_fft.rs +++ b/bi-kzg/src/bi_fft.rs @@ -48,7 +48,6 @@ fn mul_assign_vec(a: &mut [F], b: &F) { } // code copied from Halo2curves with adaption to vectors -// todo: add multi-threading // // /// Performs a radix-$2$ Fast-Fourier Transformation (FFT) on a vector of size @@ -135,7 +134,7 @@ pub fn best_fft_vec_in_place(a: &mut [F], omega: F, log_n: u32, l } /// This perform recursive butterfly arithmetic -pub fn recursive_butterfly_arithmetic( +fn recursive_butterfly_arithmetic( a: &mut [&mut [F]], m: usize, n: usize, @@ -190,20 +189,16 @@ pub fn recursive_butterfly_arithmetic( } pub(crate) fn bi_fft_in_place(coeffs: &mut [F], degree_n: usize, degree_m: usize) { + assert_eq!(coeffs.len(), degree_n * degree_m); + assert!(degree_n.is_power_of_two()); + assert!(degree_m.is_power_of_two()); + // roots of unity for supported_n and supported_m let (omega_0, omega_1) = { let omega = F::ROOT_OF_UNITY; let omega_0 = omega.pow_vartime(&[(1 << F::S) / degree_n as u64]); let omega_1 = omega.pow_vartime(&[(1 << F::S) / degree_m as u64]); - assert!( - omega_0.pow_vartime(&[degree_n as u64]) == F::ONE, - "omega_0 is not root of unity for supported_n" - ); - assert!( - omega_1.pow_vartime(&[degree_m as u64]) == F::ONE, - "omega_1 is not root of unity for supported_m" - ); (omega_0, omega_1) }; diff --git a/bi-kzg/src/coeff_form_bi_kzg.rs b/bi-kzg/src/coeff_form_bi_kzg.rs index 43eb8a19..e4ab5b92 100644 --- a/bi-kzg/src/coeff_form_bi_kzg.rs +++ b/bi-kzg/src/coeff_form_bi_kzg.rs @@ -12,11 +12,10 @@ use halo2curves::CurveAffine; use itertools::Itertools; use rand::RngCore; -// use crate::msm::best_multiexp; use crate::poly::{lagrange_coefficients, univariate_quotient}; +use crate::structs::BivariateLagrangePolynomial; use crate::structs::BivariatePolynomial; use crate::util::parallelize; -// use crate::LagrangeFormBiKZG; use crate::{ pcs::PolynomialCommitmentScheme, util::{powers_of_field_elements, tensor_product_parallel}, @@ -184,14 +183,17 @@ where let a = point.0; let b = point.1; + // u = f(a, b) let u = polynomial.evaluate(&a, &b); let timer2 = start_timer!(|| "Computing the proof pi0"); let (pi_0, f_x_b) = { + // t = f(x, b) - f(a, b) let f_x_b = polynomial.evaluate_y(&point.1); - let mut q_0_x_b = f_x_b.clone(); - q_0_x_b[0] -= u; - let q_0_x_b = univariate_quotient(&q_0_x_b, &point.0); + let mut t = f_x_b.clone(); + t[0] -= u; + // q_0(x, b) = t(x) / (x - a) + let q_0_x_b = univariate_quotient(&t, &point.0); let timer2 = start_timer!(|| format!("Computing the msm for size {}", q_0_x_b.len())); let pi_0 = best_multiexp( @@ -206,24 +208,23 @@ where let timer2 = start_timer!(|| "Computing the proof pi1"); let pi_1 = { + // t = f(x, y) - f(x, b) let mut t = polynomial.clone(); t.coefficients .iter_mut() .take(polynomial.degree_0) .zip_eq(f_x_b.iter()) .for_each(|(c, f)| *c -= f); - let coeffs = t.interpolate(); + let t_lag = t.interpolate(); - let mut divisor = vec![E::Fr::from(0); polynomial.degree_0 * polynomial.degree_1]; - divisor[0] = -point.1; - divisor[polynomial.degree_0] = E::Fr::ONE; - let divisor = - BivariatePolynomial::new(divisor, polynomial.degree_0, polynomial.degree_1); - - let divisor = divisor.interpolate(); - - // todo: batch invert - let y_minus_a_inv_lag = divisor + // divisor = (y - b) + let divisor_lag = BivariateLagrangePolynomial::from_y_monomial( + &point.1, + polynomial.degree_0, + polynomial.degree_1, + ); + let y_minus_a_inv_lag = divisor_lag + .coefficients .iter() .map(|o| { if o.is_zero_vartime() { @@ -234,7 +235,8 @@ where }) .collect::>(); - let q_1_x_y = coeffs + // q_1(x, y) = t(x, y) * (y - b)^{-1} + let q_1_x_y = t_lag .iter() .zip_eq(y_minus_a_inv_lag.iter()) .map(|(c, y)| (*c) * *y) diff --git a/bi-kzg/src/lagrange_form_bi_kzg.rs b/bi-kzg/src/lagrange_form_bi_kzg.rs index e7becd01..c3781467 100644 --- a/bi-kzg/src/lagrange_form_bi_kzg.rs +++ b/bi-kzg/src/lagrange_form_bi_kzg.rs @@ -51,9 +51,6 @@ where let tau_0 = E::Fr::random(&mut rng); let tau_1 = E::Fr::random(&mut rng); - // let tau_0 = E::Fr::from(5); - // let tau_1 = E::Fr::from(7); - let g1 = E::G1Affine::generator(); // roots of unity for supported_n and supported_m @@ -73,7 +70,6 @@ where (omega_0, omega_1) }; - // println!("start to compute the scalars"); // computes the vector of L_i^N(tau_0) * L_j^M(tau_1) for i in 0..supported_n and j in 0..supported_m let (scalars, lagrange_scalars) = { let powers_of_omega_0 = powers_of_field_elements(&omega_0, supported_n); @@ -88,7 +84,6 @@ where (scalars, lagrange_scalars) }; - // println!("start to compute the affine bases"); let g1_prog = g1.to_curve(); let coeff_bases = { let mut proj_bases = vec![E::G1::identity(); supported_n * supported_m]; @@ -107,8 +102,6 @@ where g_bases }; - // println!("start to compute the lagrange bases"); - let lagrange_bases = { let mut proj_bases = vec![E::G1::identity(); supported_n * supported_m]; parallelize(&mut proj_bases, |g, start| { @@ -129,8 +122,6 @@ where affine_bases }; - // assert_eq!(coeff_bases[..supported_n], f_x_b_scalars); - BiKZGSRS { powers_of_g: coeff_bases, powers_of_g_lagrange_over_both_roots: lagrange_bases, diff --git a/bi-kzg/src/poly.rs b/bi-kzg/src/poly.rs index 222767f7..bdb7cd81 100644 --- a/bi-kzg/src/poly.rs +++ b/bi-kzg/src/poly.rs @@ -164,41 +164,6 @@ pub(crate) fn univariate_quotient(poly: &[F], point: &F) -> Vec(coeffs: &[F], omega: &F) -> Vec { -// let n = coeffs.len(); -// let mut res = vec![F::ZERO; n]; -// for i in 0..n { -// let mut omega_i = F::ONE; -// for j in 0..n { -// res[i] += omega_i * coeffs[j]; -// omega_i *= omega; -// } -// } -// res -// } - -// /// For x in points, compute the Lagrange coefficients at x given the roots. -// /// `L_{i}(x) = \prod_{j \neq i} \frac{x - r_j}{r_i - r_j}`` -// pub(crate) fn lagrange_coefficients(roots: &[F], points: &[F]) -> Vec { -// roots -// .par_iter() -// .enumerate() -// .map(|(i, _)| { -// let mut numerator = F::ONE; -// let mut denominator = F::ONE; -// for j in 0..roots.len() { -// if i == j { -// continue; -// } -// numerator *= roots[j] - points[i]; -// denominator *= roots[j] - roots[i]; -// } -// numerator * denominator.invert().unwrap() -// }) -// .collect() -// } - impl BivariateLagrangePolynomial { fn new(coeffs: Vec, degree_0: usize, degree_1: usize) -> Self { assert_eq!(coeffs.len(), degree_0 * degree_1); @@ -212,14 +177,31 @@ impl BivariateLagrangePolynomial { impl From> for BivariateLagrangePolynomial { fn from(poly: BivariatePolynomial) -> Self { + Self::from(&poly) + } +} + +impl From<&BivariatePolynomial> for BivariateLagrangePolynomial { + fn from(poly: &BivariatePolynomial) -> Self { let coeffs = poly.interpolate(); BivariateLagrangePolynomial::new(coeffs, poly.degree_0, poly.degree_1) } } -impl From> for BivariatePolynomial { - fn from(_poly: BivariateLagrangePolynomial) -> Self { - todo!() +impl BivariateLagrangePolynomial { + /// construct a bivariate lagrange polynomial from a monomial f(y) = y - b + pub(crate) fn from_y_monomial(b: &F, n: usize, m: usize) -> Self { + // roots of unity for supported_n and supported_m + let omega_1 = { + let omega = F::ROOT_OF_UNITY; + omega.pow_vartime(&[(1 << F::S) / m as u64]) + }; + let mut coeffs = vec![F::ZERO; n * m]; + for i in 0..m { + let element = omega_1.pow_vartime(&[i as u64]) - *b; + coeffs[i * n..(i + 1) * n].copy_from_slice(vec![element; n].as_slice()); + } + BivariateLagrangePolynomial::new(coeffs, n, m) } } @@ -327,22 +309,6 @@ mod tests { ); let eval_at_y = poly.evaluate_y(&Fr::from(10u64)); assert_eq!(eval_at_y, vec![Fr::from(7531u64), Fr::from(8642u64)]); - - // let poly = BivariatePolynomial::new( - // vec![ - // Fr::from(1u64), - // Fr::from(0u64), - // Fr::from(1u64), - // Fr::from(0u64), - // Fr::from(0u64), - // Fr::from(0u64), - // Fr::from(0u64), - // Fr::from(0u64), - // ], - // 2, - // 4, - // ); - // println!("poly: {:?}", poly.lagrange_coeffs()); } #[test] @@ -452,4 +418,27 @@ mod tests { "0x0000000000000000000000000000000000000000000000000000000000000000" ); } + + #[test] + fn test_from_y() { + let b = Fr::from(10u64); + let n = 2; + let m = 4; + let poly1 = super::BivariateLagrangePolynomial::from_y_monomial(&b, n, m); + let poly2 = super::BivariatePolynomial::new( + vec![ + -b, + Fr::from(0u64), + Fr::from(1u64), + Fr::from(0u64), + Fr::from(0u64), + Fr::from(0u64), + Fr::from(0u64), + Fr::from(0u64), + ], + n, + m, + ); + assert_eq!(poly1.coefficients, poly2.interpolate()); + } } From 37cb42f65cdae220cd33513763f1da2933f03a11 Mon Sep 17 00:00:00 2001 From: zhenfei Date: Tue, 18 Jun 2024 20:56:20 -0400 Subject: [PATCH 31/31] clean up; fix clippy --- bi-kzg/src/bi_fft.rs | 71 +------ bi-kzg/src/coeff_form_bi_kzg.rs | 49 +---- bi-kzg/src/lagrange_form_bi_kzg.rs | 21 +- bi-kzg/src/lib.rs | 6 +- bi-kzg/src/pcs.rs | 27 +-- bi-kzg/src/poly.rs | 264 ++---------------------- bi-kzg/src/structs.rs | 79 +------- bi-kzg/src/tests.rs | 310 +++++++++++++++++++++++++++-- bi-kzg/src/util.rs | 2 +- 9 files changed, 341 insertions(+), 488 deletions(-) diff --git a/bi-kzg/src/bi_fft.rs b/bi-kzg/src/bi_fft.rs index acf87772..1ac7fd5d 100644 --- a/bi-kzg/src/bi_fft.rs +++ b/bi-kzg/src/bi_fft.rs @@ -21,6 +21,7 @@ fn deep_swap_chunks(a: &mut [&mut [F]], rk: usize, k: usize) { let x = a[k].as_mut_ptr(); let y = a[rk].as_mut_ptr(); unsafe { + // is there a for i in 0..a[k].len() { std::ptr::swap(x.add(i), y.add(i)); } @@ -129,7 +130,7 @@ pub fn best_fft_vec_in_place(a: &mut [F], omega: F, log_n: u32, l twiddle_chunk /= 2; } } else { - recursive_butterfly_arithmetic(&mut a_vec_ptrs, m, n, 1, &twiddles) + recursive_butterfly_arithmetic(&mut a_vec_ptrs, m, 1, &twiddles) } } @@ -137,7 +138,6 @@ pub fn best_fft_vec_in_place(a: &mut [F], omega: F, log_n: u32, l fn recursive_butterfly_arithmetic( a: &mut [&mut [F]], m: usize, - n: usize, twiddle_chunk: usize, twiddles: &[F], ) { @@ -154,8 +154,8 @@ fn recursive_butterfly_arithmetic( } else { let (left, right) = a.split_at_mut(m / 2); rayon::join( - || recursive_butterfly_arithmetic(left, m / 2, n, twiddle_chunk * 2, twiddles), - || recursive_butterfly_arithmetic(right, m / 2, n, twiddle_chunk * 2, twiddles), + || recursive_butterfly_arithmetic(left, m / 2, twiddle_chunk * 2, twiddles), + || recursive_butterfly_arithmetic(right, m / 2, twiddle_chunk * 2, twiddles), ); // case when twiddle factor is one @@ -188,6 +188,7 @@ fn recursive_butterfly_arithmetic( } } +/// Convert a polynomial in coefficient form to evaluation form using a two layer FFT pub(crate) fn bi_fft_in_place(coeffs: &mut [F], degree_n: usize, degree_m: usize) { assert_eq!(coeffs.len(), degree_n * degree_m); assert!(degree_n.is_power_of_two()); @@ -196,71 +197,17 @@ pub(crate) fn bi_fft_in_place(coeffs: &mut [F], degree_n: usize, // roots of unity for supported_n and supported_m let (omega_0, omega_1) = { let omega = F::ROOT_OF_UNITY; - let omega_0 = omega.pow_vartime(&[(1 << F::S) / degree_n as u64]); - let omega_1 = omega.pow_vartime(&[(1 << F::S) / degree_m as u64]); + let omega_0 = omega.pow_vartime([(1 << F::S) / degree_n as u64]); + let omega_1 = omega.pow_vartime([(1 << F::S) / degree_m as u64]); (omega_0, omega_1) }; + // inner layer of FFT over variable x coeffs .chunks_exact_mut(degree_n) .for_each(|chunk| best_fft(chunk, omega_0, log2(degree_n))); + // outer layer of FFT over variable y best_fft_vec_in_place(coeffs, omega_1, log2(degree_n), log2(degree_m)); } - -#[cfg(test)] -mod tests { - use ark_std::test_rng; - use halo2curves::bn256::Fr; - - use crate::BivariatePolynomial; - - use super::bi_fft_in_place; - - #[test] - fn test_bi_fft() { - { - let n = 4; - let m = 4; - let poly = BivariatePolynomial::new( - vec![ - Fr::from(1u64), - Fr::from(2u64), - Fr::from(4u64), - Fr::from(8u64), - Fr::from(16u64), - Fr::from(32u64), - Fr::from(64u64), - Fr::from(128u64), - Fr::from(256u64), - Fr::from(128u64), - Fr::from(64u64), - Fr::from(32u64), - Fr::from(16u64), - Fr::from(8u64), - Fr::from(4u64), - Fr::from(2u64), - ], - n, - m, - ); - let mut poly_lag2 = poly.coefficients.clone(); - let poly_lag = poly.interpolate(); - bi_fft_in_place(&mut poly_lag2, n, m); - assert_eq!(poly_lag, poly_lag2); - } - - let mut rng = test_rng(); - - for m in [2, 4, 8, 16, 32, 64].iter() { - for n in [2, 4, 8, 16, 32, 64].iter() { - let poly = BivariatePolynomial::::random(&mut rng, *n, *m); - let mut poly_lag2 = poly.coefficients.clone(); - let poly_lag = poly.evaluate_at_roots(); - bi_fft_in_place(&mut poly_lag2, *n, *m); - assert_eq!(poly_lag, poly_lag2); - } - } - } -} diff --git a/bi-kzg/src/coeff_form_bi_kzg.rs b/bi-kzg/src/coeff_form_bi_kzg.rs index e4ab5b92..4f4eb908 100644 --- a/bi-kzg/src/coeff_form_bi_kzg.rs +++ b/bi-kzg/src/coeff_form_bi_kzg.rs @@ -47,36 +47,30 @@ where supported_n: usize, supported_m: usize, ) -> Self::SRS { - // LagrangeFormBiKZG::::gen_srs_for_testing(rng, supported_n, supported_m) - assert!(supported_n.is_power_of_two()); assert!(supported_m.is_power_of_two()); let tau_0 = E::Fr::random(&mut rng); let tau_1 = E::Fr::random(&mut rng); - // let tau_0 = E::Fr::from(5); - // let tau_1 = E::Fr::from(7); - let g1 = E::G1Affine::generator(); // roots of unity for supported_n and supported_m let (omega_0, omega_1) = { let omega = E::Fr::ROOT_OF_UNITY; - let omega_0 = omega.pow_vartime(&[(1 << E::Fr::S) / supported_n as u64]); - let omega_1 = omega.pow_vartime(&[(1 << E::Fr::S) / supported_m as u64]); + let omega_0 = omega.pow_vartime([(1 << E::Fr::S) / supported_n as u64]); + let omega_1 = omega.pow_vartime([(1 << E::Fr::S) / supported_m as u64]); assert!( - omega_0.pow_vartime(&[supported_n as u64]) == E::Fr::ONE, + omega_0.pow_vartime([supported_n as u64]) == E::Fr::ONE, "omega_0 is not root of unity for supported_n" ); assert!( - omega_1.pow_vartime(&[supported_m as u64]) == E::Fr::ONE, + omega_1.pow_vartime([supported_m as u64]) == E::Fr::ONE, "omega_1 is not root of unity for supported_m" ); (omega_0, omega_1) }; - // println!("start to compute the scalars"); // computes the vector of L_i^N(tau_0) * L_j^M(tau_1) for i in 0..supported_n and j in 0..supported_m let (scalars, lagrange_scalars) = { let powers_of_omega_0 = powers_of_field_elements(&omega_0, supported_n); @@ -91,7 +85,6 @@ where (scalars, lagrange_scalars) }; - // println!("start to compute the affine bases"); let g1_prog = g1.to_curve(); let coeff_bases = { let mut proj_bases = vec![E::G1::identity(); supported_n * supported_m]; @@ -110,8 +103,6 @@ where g_bases }; - // println!("start to compute the lagrange bases"); - let lagrange_bases = { let mut proj_bases = vec![E::G1::identity(); supported_n * supported_m]; parallelize(&mut proj_bases, |g, start| { @@ -132,8 +123,6 @@ where affine_bases }; - // assert_eq!(coeff_bases[..supported_n], f_x_b_scalars); - BiKZGSRS { powers_of_g: coeff_bases, powers_of_g_lagrange_over_both_roots: lagrange_bases, @@ -189,7 +178,7 @@ where let timer2 = start_timer!(|| "Computing the proof pi0"); let (pi_0, f_x_b) = { // t = f(x, b) - f(a, b) - let f_x_b = polynomial.evaluate_y(&point.1); + let f_x_b = polynomial.evaluate_at_y(&point.1); let mut t = f_x_b.clone(); t[0] -= u; // q_0(x, b) = t(x) / (x - a) @@ -274,14 +263,10 @@ where where E: MultiMillerLoop, { + let timers = start_timer!(|| "Verifying the proof"); let pi0_a_pi1_b_g1_cmu = best_multiexp( &[point.0, point.1, E::Fr::ONE, -*value], - &[ - proof.pi0, - proof.pi1, - commitment.com.into(), - verifier_param.g.into(), - ], + &[proof.pi0, proof.pi1, commitment.com, verifier_param.g], ); let pi0_a_pi1_b_g1_cmu = (-pi0_a_pi1_b_g1_cmu).to_affine(); let res = E::multi_miller_loop(&[ @@ -290,25 +275,9 @@ where (&pi0_a_pi1_b_g1_cmu, &verifier_param.h.into()), ]); let res = res.final_exponentiation().is_identity().into(); - + end_timer!(timers); res } - fn multi_open( - _prover_param: impl Borrow, - _polynomials: &[Self::Polynomial], - _points: &[Self::Point], - _evals: &[Self::Evaluation], - ) -> Self::BatchProof { - unimplemented!() - } - - fn batch_verify( - _verifier_param: &Self::VerifierParam, - _commitments: &[Self::Commitment], - _points: &[Self::Point], - _batch_proof: &Self::BatchProof, - ) -> bool { - unimplemented!() - } + // TODO: implement multi-opening and batch verification } diff --git a/bi-kzg/src/lagrange_form_bi_kzg.rs b/bi-kzg/src/lagrange_form_bi_kzg.rs index c3781467..ffa0a738 100644 --- a/bi-kzg/src/lagrange_form_bi_kzg.rs +++ b/bi-kzg/src/lagrange_form_bi_kzg.rs @@ -1,3 +1,5 @@ +//! We don't need this file for now. We will use the `CoeffFormBiKZG`. + use std::{borrow::Borrow, marker::PhantomData}; use ark_std::{end_timer, start_timer}; @@ -276,21 +278,6 @@ where res } - fn multi_open( - _prover_param: impl Borrow, - _polynomials: &[Self::Polynomial], - _points: &[Self::Point], - _evals: &[Self::Evaluation], - ) -> Self::BatchProof { - unimplemented!() - } - - fn batch_verify( - _verifier_param: &Self::VerifierParam, - _commitments: &[Self::Commitment], - _points: &[Self::Point], - _batch_proof: &Self::BatchProof, - ) -> bool { - unimplemented!() - } + + // TODO: implement multi-opening and batch verification } diff --git a/bi-kzg/src/lib.rs b/bi-kzg/src/lib.rs index 96079f99..3d4f5d8d 100644 --- a/bi-kzg/src/lib.rs +++ b/bi-kzg/src/lib.rs @@ -1,16 +1,18 @@ mod bi_fft; mod coeff_form_bi_kzg; -// mod lagrange_form_bi_kzg; mod pcs; mod poly; mod structs; mod util; +// mod lagrange_form_bi_kzg; + #[cfg(test)] mod tests; pub use coeff_form_bi_kzg::CoeffFormBiKZG; -// pub use lagrange_form_bi_kzg::LagrangeFormBiKZG; pub use pcs::PolynomialCommitmentScheme; pub use structs::BivariatePolynomial; pub use structs::{BiKZGCommitment, BiKZGProof, BiKZGSRS, BiKZGVerifierParam}; + +// pub use lagrange_form_bi_kzg::LagrangeFormBiKZG; diff --git a/bi-kzg/src/pcs.rs b/bi-kzg/src/pcs.rs index cb54a764..8a32ccd0 100644 --- a/bi-kzg/src/pcs.rs +++ b/bi-kzg/src/pcs.rs @@ -1,6 +1,6 @@ use std::{borrow::Borrow, fmt::Debug}; -use halo2curves::{ff::Field, serde::SerdeObject}; +use halo2curves::ff::Field; use rand::RngCore; /// This trait defines APIs for polynomial commitment schemes. @@ -21,9 +21,9 @@ pub trait PolynomialCommitmentScheme { /// Polynomial Evaluation type Evaluation: Field; /// Commitments - type Commitment: Clone + SerdeObject + Debug; + type Commitment: Clone + Debug; /// Proofs - type Proof: Clone + SerdeObject + Debug; + type Proof: Clone + Debug; /// Batch proofs type BatchProof; @@ -34,22 +34,6 @@ pub trait PolynomialCommitmentScheme { /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION. fn gen_srs_for_testing(rng: impl RngCore, supported_n: usize, supported_m: usize) -> Self::SRS; - // /// Trim the universal parameters to specialize the public parameters. - // /// Input both `supported_degree` for univariate and - // /// `supported_num_vars` for multilinear. - // /// ## Note on function signature - // /// Usually, data structure like SRS and ProverParam are huge and users - // /// might wish to keep them in heap using different kinds of smart pointers - // /// (instead of only in stack) therefore our `impl Borrow<_>` interface - // /// allows for passing in any pointer type, e.g.: `trim(srs: &Self::SRS, - // /// ..)` or `trim(srs: Box, ..)` or `trim(srs: Arc, - // /// ..)` etc. - // fn trim( - // srs: impl Borrow, - // supported_degree: Option, - // supported_num_vars: Option, - // ) -> (Self::ProverParam, Self::VerifierParam); - /// Generate a commitment for a polynomial /// ## Note on function signature /// Usually, data structure like SRS and ProverParam are huge and users @@ -72,14 +56,12 @@ pub trait PolynomialCommitmentScheme { point: &Self::Point, ) -> (Self::Proof, Self::Evaluation); - /// Input a list of multilinear extensions, and a same number of points, and - /// a transcript, compute a multi-opening for all the polynomials. + /// Input a list of polynomials, and a same number of points, compute a multi-opening for all the polynomials. fn multi_open( _prover_param: impl Borrow, _polynomials: &[Self::Polynomial], _points: &[Self::Point], _evals: &[Self::Evaluation], - // _transcript: &mut IOPTranscript, ) -> Self::BatchProof { // the reason we use unimplemented!() is to enable developers to implement the // trait without always implementing the batching APIs. @@ -103,7 +85,6 @@ pub trait PolynomialCommitmentScheme { _commitments: &[Self::Commitment], _points: &[Self::Point], _batch_proof: &Self::BatchProof, - // _transcript: &mut IOPTranscript, ) -> bool { // the reason we use unimplemented!() is to enable developers to implement the // trait without always implementing the batching APIs. diff --git a/bi-kzg/src/poly.rs b/bi-kzg/src/poly.rs index bdb7cd81..47df6675 100644 --- a/bi-kzg/src/poly.rs +++ b/bi-kzg/src/poly.rs @@ -26,6 +26,7 @@ impl BivariatePolynomial { Self::new(coefficients, degree_0, degree_1) } + /// evaluate the polynomial at (x, y) pub fn evaluate(&self, x: &F, y: &F) -> F { let x_power = powers_of_field_elements(x, self.degree_0); let y_power = powers_of_field_elements(y, self.degree_1); @@ -42,7 +43,8 @@ impl BivariatePolynomial { }) } - pub fn evaluate_y(&self, y: &F) -> Vec { + /// evaluate the polynomial at y, return a univariate polynomial in x + pub fn evaluate_at_y(&self, y: &F) -> Vec { let mut f_x_b = self.coefficients[0..self.degree_0].to_vec(); let powers_of_b = powers_of_field_elements(y, self.degree_1); powers_of_b @@ -69,15 +71,15 @@ impl BivariatePolynomial { // roots of unity for supported_n and supported_m let (omega_0, omega_1) = { let omega = F::ROOT_OF_UNITY; - let omega_0 = omega.pow_vartime(&[(1 << F::S) / self.degree_0 as u64]); - let omega_1 = omega.pow_vartime(&[(1 << F::S) / self.degree_1 as u64]); + let omega_0 = omega.pow_vartime([(1 << F::S) / self.degree_0 as u64]); + let omega_1 = omega.pow_vartime([(1 << F::S) / self.degree_1 as u64]); assert!( - omega_0.pow_vartime(&[self.degree_0 as u64]) == F::ONE, + omega_0.pow_vartime([self.degree_0 as u64]) == F::ONE, "omega_0 is not root of unity for supported_n" ); assert!( - omega_1.pow_vartime(&[self.degree_1 as u64]) == F::ONE, + omega_1.pow_vartime([self.degree_1 as u64]) == F::ONE, "omega_1 is not root of unity for supported_m" ); (omega_0, omega_1) @@ -109,8 +111,8 @@ impl BivariatePolynomial { } } -/// For x in points, compute the Lagrange coefficients at x given the roots. -/// `L_{i}(x) = \prod_{j \neq i} \frac{x - r_j}{r_i - r_j}`` +/// For a point x, compute the coefficients of Lagrange polynomial L_{i}(x) at x, given the roots. +/// `L_{i}(x) = \prod_{j \neq i} \frac{x - r_j}{r_i - r_j}` pub(crate) fn lagrange_coefficients(roots: &[F], points: &F) -> Vec { roots .par_iter() @@ -130,13 +132,11 @@ pub(crate) fn lagrange_coefficients(roots: &[F], points: .collect() } -/// Compute poly / (x-point) -/// -// TODO: this algorithm is quadratic. is this more efficient than FFT? +/// Compute poly / (x-point) using univariate division pub(crate) fn univariate_quotient(poly: &[F], point: &F) -> Vec { let timer = start_timer!(|| format!("Univariate quotient of degree {}", poly.len())); let mut dividend_coeff = poly.to_vec(); - let divisor = vec![-*point, F::from(1u64)]; + let divisor = [-*point, F::from(1u64)]; let mut coefficients = vec![]; let mut dividend_pos = dividend_coeff.len() - 1; @@ -194,251 +194,13 @@ impl BivariateLagrangePolynomial { // roots of unity for supported_n and supported_m let omega_1 = { let omega = F::ROOT_OF_UNITY; - omega.pow_vartime(&[(1 << F::S) / m as u64]) + omega.pow_vartime([(1 << F::S) / m as u64]) }; let mut coeffs = vec![F::ZERO; n * m]; for i in 0..m { - let element = omega_1.pow_vartime(&[i as u64]) - *b; + let element = omega_1.pow_vartime([i as u64]) - *b; coeffs[i * n..(i + 1) * n].copy_from_slice(vec![element; n].as_slice()); } BivariateLagrangePolynomial::new(coeffs, n, m) } } - -#[cfg(test)] -mod tests { - use crate::structs::BivariatePolynomial; - use halo2curves::bn256::Fr; - - #[test] - fn test_bivariate_poly_eval() { - { - let poly = BivariatePolynomial::new( - vec![ - Fr::from(1u64), - Fr::from(2u64), - Fr::from(3u64), - Fr::from(4u64), - ], - 2, - 2, - ); - let x = Fr::from(5u64); - let y = Fr::from(7u64); - let result = poly.evaluate(&x, &y); - assert_eq!( - result, - Fr::from(1u64) + Fr::from(2u64) * x + Fr::from(3u64) * y + Fr::from(4u64) * x * y - ); - } - - { - let poly = BivariatePolynomial::new( - vec![ - Fr::from(1u64), - Fr::from(2u64), - Fr::from(3u64), - Fr::from(4u64), - Fr::from(5u64), - Fr::from(6u64), - Fr::from(7u64), - Fr::from(8u64), - ], - 2, - 4, - ); - let x = Fr::from(9u64); - let y = Fr::from(10u64); - let result = poly.evaluate(&x, &y); - assert_eq!( - result, - Fr::from(1u64) - + Fr::from(2u64) * x - + (Fr::from(3u64) + Fr::from(4u64) * x) * y - + (Fr::from(5u64) + Fr::from(6u64) * x) * y * y - + (Fr::from(7u64) + Fr::from(8u64) * x) * y * y * y - ); - } - - let poly = BivariatePolynomial::new( - vec![ - Fr::from(1u64), - Fr::from(2u64), - Fr::from(3u64), - Fr::from(4u64), - Fr::from(5u64), - Fr::from(6u64), - Fr::from(7u64), - Fr::from(8u64), - ], - 4, - 2, - ); - let x = Fr::from(9u64); - let y = Fr::from(10u64); - let result = poly.evaluate(&x, &y); - assert_eq!( - result, - Fr::from(1u64) - + Fr::from(2u64) * x - + Fr::from(3u64) * x * x - + Fr::from(4u64) * x * x * x - + (Fr::from(5u64) - + Fr::from(6u64) * x - + Fr::from(7u64) * x * x - + Fr::from(8u64) * x * x * x) - * y - ); - } - - #[test] - fn test_eval_at_y() { - let poly = BivariatePolynomial::new( - vec![ - Fr::from(1u64), - Fr::from(2u64), - Fr::from(3u64), - Fr::from(4u64), - Fr::from(5u64), - Fr::from(6u64), - Fr::from(7u64), - Fr::from(8u64), - ], - 2, - 4, - ); - let eval_at_y = poly.evaluate_y(&Fr::from(10u64)); - assert_eq!(eval_at_y, vec![Fr::from(7531u64), Fr::from(8642u64)]); - } - - #[test] - fn test_poly_div() { - { - // x^3 + 1 = (x + 1)(x^2 - x + 1) - let poly = vec![ - Fr::from(1u64), - Fr::from(0u64), - Fr::from(0u64), - Fr::from(1u64), - ]; - let point = -Fr::from(1u64); - let result = super::univariate_quotient(&poly, &point); - assert_eq!( - result, - vec![ - Fr::from(1u64), - -Fr::from(1u64), - Fr::from(1u64), - Fr::from(0u64) - ] - ); - } - { - // x^3 - 1 = (x-1)(x^2 + x + 1) - let poly = vec![ - -Fr::from(1u64), - Fr::from(0u64), - Fr::from(0u64), - Fr::from(1u64), - ]; - let point = Fr::from(1u64); - let result = super::univariate_quotient(&poly, &point); - assert_eq!( - result, - vec![ - Fr::from(1u64), - Fr::from(1u64), - Fr::from(1u64), - Fr::from(0u64) - ] - ); - } - } - - #[test] - fn test_lagrange_coeffs() { - let poly = BivariatePolynomial::new( - vec![ - Fr::from(1u64), - Fr::from(2u64), - Fr::from(3u64), - Fr::from(4u64), - Fr::from(5u64), - Fr::from(6u64), - Fr::from(7u64), - Fr::from(8u64), - ], - 2, - 4, - ); - - let lagrange_coeffs = poly.interpolate(); - - // From sage script - // poly_lag_coeff = [ - // 0x0000000000000000000000000000000000000000000000000000000000000024, - // 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffffd, - // 0x00000000000000059e26bcea0d48bac65a4e1a8be2302529067f891b047e4e50, - // 0x0000000000000000000000000000000000000000000000000000000000000000, - // 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff9, - // 0x0000000000000000000000000000000000000000000000000000000000000000, - // 0x30644e72e131a0241a2988cc74389d96cde5cdbc97894b683d626c78eb81b1a1, - // 0x0000000000000000000000000000000000000000000000000000000000000000] - assert_eq!(lagrange_coeffs.len(), 8); - assert_eq!( - format!("{:?}", lagrange_coeffs[0]), - "0x0000000000000000000000000000000000000000000000000000000000000024" - ); - assert_eq!( - format!("{:?}", lagrange_coeffs[1]), - "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffffd" - ); - assert_eq!( - format!("{:?}", lagrange_coeffs[2]), - "0x00000000000000059e26bcea0d48bac65a4e1a8be2302529067f891b047e4e50" - ); - assert_eq!( - format!("{:?}", lagrange_coeffs[3]), - "0x0000000000000000000000000000000000000000000000000000000000000000" - ); - assert_eq!( - format!("{:?}", lagrange_coeffs[4]), - "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff9" - ); - assert_eq!( - format!("{:?}", lagrange_coeffs[5]), - "0x0000000000000000000000000000000000000000000000000000000000000000" - ); - assert_eq!( - format!("{:?}", lagrange_coeffs[6]), - "0x30644e72e131a0241a2988cc74389d96cde5cdbc97894b683d626c78eb81b1a1" - ); - assert_eq!( - format!("{:?}", lagrange_coeffs[7]), - "0x0000000000000000000000000000000000000000000000000000000000000000" - ); - } - - #[test] - fn test_from_y() { - let b = Fr::from(10u64); - let n = 2; - let m = 4; - let poly1 = super::BivariateLagrangePolynomial::from_y_monomial(&b, n, m); - let poly2 = super::BivariatePolynomial::new( - vec![ - -b, - Fr::from(0u64), - Fr::from(1u64), - Fr::from(0u64), - Fr::from(0u64), - Fr::from(0u64), - Fr::from(0u64), - Fr::from(0u64), - ], - n, - m, - ); - assert_eq!(poly1.coefficients, poly2.interpolate()); - } -} diff --git a/bi-kzg/src/structs.rs b/bi-kzg/src/structs.rs index eea62a42..0bc3eeaf 100644 --- a/bi-kzg/src/structs.rs +++ b/bi-kzg/src/structs.rs @@ -1,6 +1,4 @@ -use std::io::{self, Read, Write}; - -use halo2curves::{pairing::Engine, serde::SerdeObject}; +use halo2curves::pairing::Engine; #[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct BivariatePolynomial { @@ -36,13 +34,6 @@ pub struct BiKZGSRS { pub tau_1_h: E::G2Affine, } -// /// `BiKZGProverParam` is used to generate a proof -// #[derive(Clone, Debug, Eq, PartialEq, Default)] -// pub struct BiKZGProverParam { -// /// Parameters -// pub powers_of_g: Vec, -// } - /// `UnivariateVerifierParam` is used to check evaluation proofs for a given /// commitment. #[derive(Clone, Debug, Eq, PartialEq, Default)] @@ -82,71 +73,3 @@ impl From<&BiKZGSRS> for BiKZGVerifierParam { } } } - -impl SerdeObject for BiKZGCommitment { - /// The purpose of unchecked functions is to read the internal memory representation - /// of a type from bytes as quickly as possible. No sanitization checks are performed - /// to ensure the bytes represent a valid object. As such this function should only be - /// used internally as an extension of machine memory. It should not be used to deserialize - /// externally provided data. - fn from_raw_bytes_unchecked(_bytes: &[u8]) -> Self { - todo!("Implement this function") - } - fn from_raw_bytes(_bytes: &[u8]) -> Option { - todo!("Implement this function") - } - - fn to_raw_bytes(&self) -> Vec { - todo!("Implement this function") - } - - /// The purpose of unchecked functions is to read the internal memory representation - /// of a type from disk as quickly as possible. No sanitization checks are performed - /// to ensure the bytes represent a valid object. This function should only be used - /// internally when some machine state cannot be kept in memory (e.g., between runs) - /// and needs to be reloaded as quickly as possible. - fn read_raw_unchecked(_reader: &mut R) -> Self { - todo!("Implement this function") - } - fn read_raw(_reader: &mut R) -> io::Result { - todo!("Implement this function") - } - - fn write_raw(&self, _writer: &mut W) -> io::Result<()> { - todo!("Implement this function") - } -} - -impl SerdeObject for BiKZGProof { - /// The purpose of unchecked functions is to read the internal memory representation - /// of a type from bytes as quickly as possible. No sanitization checks are performed - /// to ensure the bytes represent a valid object. As such this function should only be - /// used internally as an extension of machine memory. It should not be used to deserialize - /// externally provided data. - fn from_raw_bytes_unchecked(_bytes: &[u8]) -> Self { - todo!("Implement this function") - } - fn from_raw_bytes(_bytes: &[u8]) -> Option { - todo!("Implement this function") - } - - fn to_raw_bytes(&self) -> Vec { - todo!("Implement this function") - } - - /// The purpose of unchecked functions is to read the internal memory representation - /// of a type from disk as quickly as possible. No sanitization checks are performed - /// to ensure the bytes represent a valid object. This function should only be used - /// internally when some machine state cannot be kept in memory (e.g., between runs) - /// and needs to be reloaded as quickly as possible. - fn read_raw_unchecked(_reader: &mut R) -> Self { - todo!("Implement this function") - } - fn read_raw(_reader: &mut R) -> io::Result { - todo!("Implement this function") - } - - fn write_raw(&self, _writer: &mut W) -> io::Result<()> { - todo!("Implement this function") - } -} diff --git a/bi-kzg/src/tests.rs b/bi-kzg/src/tests.rs index f79a9f31..4b20c041 100644 --- a/bi-kzg/src/tests.rs +++ b/bi-kzg/src/tests.rs @@ -5,13 +5,17 @@ use halo2curves::{ }; use crate::{ - coeff_form_bi_kzg::CoeffFormBiKZG, pcs::PolynomialCommitmentScheme, - poly::lagrange_coefficients, util::tensor_product_parallel, BiKZGVerifierParam, - BivariatePolynomial, + bi_fft::bi_fft_in_place, + coeff_form_bi_kzg::CoeffFormBiKZG, + pcs::PolynomialCommitmentScheme, + poly::{lagrange_coefficients, univariate_quotient}, + structs::BivariateLagrangePolynomial, + util::tensor_product_parallel, + BiKZGVerifierParam, BivariatePolynomial, }; #[test] -fn test_bi_kzg_with_profiling() { +fn test_bi_kzg_single_pass() { let mut rng = test_rng(); let n = 16; let m = 32; @@ -98,16 +102,6 @@ fn test_bi_kzg_e2e() { } } -#[test] -fn test_lagrange_coeffs() { - let roots = vec![Fr::from(1u64), Fr::from(2u64), Fr::from(3u64)]; - let point = Fr::from(4u64); - let result = lagrange_coefficients(&roots, &point); - assert_eq!(result[0], Fr::from(1u64)); - assert_eq!(result[1], -Fr::from(3u64)); - assert_eq!(result[2], Fr::from(3u64)); -} - #[test] fn test_tensor_product() { let vec1 = vec![Fr::from(1u64), Fr::from(2u64), Fr::from(3u64)]; @@ -123,3 +117,291 @@ fn test_tensor_product() { assert_eq!(result[7], Fr::from(2u64) * Fr::from(6u64)); assert_eq!(result[8], Fr::from(3u64) * Fr::from(6u64)); } + +#[test] +fn test_bivariate_poly_eval() { + { + let poly = BivariatePolynomial::new( + vec![ + Fr::from(1u64), + Fr::from(2u64), + Fr::from(3u64), + Fr::from(4u64), + ], + 2, + 2, + ); + let x = Fr::from(5u64); + let y = Fr::from(7u64); + let result = poly.evaluate(&x, &y); + assert_eq!( + result, + Fr::from(1u64) + Fr::from(2u64) * x + Fr::from(3u64) * y + Fr::from(4u64) * x * y + ); + } + + { + let poly = BivariatePolynomial::new( + vec![ + Fr::from(1u64), + Fr::from(2u64), + Fr::from(3u64), + Fr::from(4u64), + Fr::from(5u64), + Fr::from(6u64), + Fr::from(7u64), + Fr::from(8u64), + ], + 2, + 4, + ); + let x = Fr::from(9u64); + let y = Fr::from(10u64); + let result = poly.evaluate(&x, &y); + assert_eq!( + result, + Fr::from(1u64) + + Fr::from(2u64) * x + + (Fr::from(3u64) + Fr::from(4u64) * x) * y + + (Fr::from(5u64) + Fr::from(6u64) * x) * y * y + + (Fr::from(7u64) + Fr::from(8u64) * x) * y * y * y + ); + } + + let poly = BivariatePolynomial::new( + vec![ + Fr::from(1u64), + Fr::from(2u64), + Fr::from(3u64), + Fr::from(4u64), + Fr::from(5u64), + Fr::from(6u64), + Fr::from(7u64), + Fr::from(8u64), + ], + 4, + 2, + ); + let x = Fr::from(9u64); + let y = Fr::from(10u64); + let result = poly.evaluate(&x, &y); + assert_eq!( + result, + Fr::from(1u64) + + Fr::from(2u64) * x + + Fr::from(3u64) * x * x + + Fr::from(4u64) * x * x * x + + (Fr::from(5u64) + + Fr::from(6u64) * x + + Fr::from(7u64) * x * x + + Fr::from(8u64) * x * x * x) + * y + ); +} + +#[test] +fn test_eval_at_y() { + let poly = BivariatePolynomial::new( + vec![ + Fr::from(1u64), + Fr::from(2u64), + Fr::from(3u64), + Fr::from(4u64), + Fr::from(5u64), + Fr::from(6u64), + Fr::from(7u64), + Fr::from(8u64), + ], + 2, + 4, + ); + let eval_at_y = poly.evaluate_at_y(&Fr::from(10u64)); + assert_eq!(eval_at_y, vec![Fr::from(7531u64), Fr::from(8642u64)]); +} + +#[test] +fn test_univariate_division() { + { + // x^3 + 1 = (x + 1)(x^2 - x + 1) + let poly = vec![ + Fr::from(1u64), + Fr::from(0u64), + Fr::from(0u64), + Fr::from(1u64), + ]; + let point = -Fr::from(1u64); + let result = univariate_quotient(&poly, &point); + assert_eq!( + result, + vec![ + Fr::from(1u64), + -Fr::from(1u64), + Fr::from(1u64), + Fr::from(0u64) + ] + ); + } + { + // x^3 - 1 = (x-1)(x^2 + x + 1) + let poly = vec![ + -Fr::from(1u64), + Fr::from(0u64), + Fr::from(0u64), + Fr::from(1u64), + ]; + let point = Fr::from(1u64); + let result = univariate_quotient(&poly, &point); + assert_eq!( + result, + vec![ + Fr::from(1u64), + Fr::from(1u64), + Fr::from(1u64), + Fr::from(0u64) + ] + ); + } +} + +#[test] +fn test_lagrange_coeffs() { + let roots = vec![Fr::from(1u64), Fr::from(2u64), Fr::from(3u64)]; + let point = Fr::from(4u64); + let result = lagrange_coefficients(&roots, &point); + assert_eq!(result[0], Fr::from(1u64)); + assert_eq!(result[1], -Fr::from(3u64)); + assert_eq!(result[2], Fr::from(3u64)); +} + +#[test] +fn test_interpolation() { + let poly = BivariatePolynomial::new( + vec![ + Fr::from(1u64), + Fr::from(2u64), + Fr::from(3u64), + Fr::from(4u64), + Fr::from(5u64), + Fr::from(6u64), + Fr::from(7u64), + Fr::from(8u64), + ], + 2, + 4, + ); + + let lagrange_coeffs = poly.interpolate(); + + // From sage script + // poly_lag_coeff = [ + // 0x0000000000000000000000000000000000000000000000000000000000000024, + // 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffffd, + // 0x00000000000000059e26bcea0d48bac65a4e1a8be2302529067f891b047e4e50, + // 0x0000000000000000000000000000000000000000000000000000000000000000, + // 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff9, + // 0x0000000000000000000000000000000000000000000000000000000000000000, + // 0x30644e72e131a0241a2988cc74389d96cde5cdbc97894b683d626c78eb81b1a1, + // 0x0000000000000000000000000000000000000000000000000000000000000000] + assert_eq!(lagrange_coeffs.len(), 8); + assert_eq!( + format!("{:?}", lagrange_coeffs[0]), + "0x0000000000000000000000000000000000000000000000000000000000000024" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[1]), + "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffffd" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[2]), + "0x00000000000000059e26bcea0d48bac65a4e1a8be2302529067f891b047e4e50" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[3]), + "0x0000000000000000000000000000000000000000000000000000000000000000" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[4]), + "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff9" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[5]), + "0x0000000000000000000000000000000000000000000000000000000000000000" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[6]), + "0x30644e72e131a0241a2988cc74389d96cde5cdbc97894b683d626c78eb81b1a1" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[7]), + "0x0000000000000000000000000000000000000000000000000000000000000000" + ); +} + +#[test] +fn test_from_y() { + let b = Fr::from(10u64); + let n = 2; + let m = 4; + let poly1 = BivariateLagrangePolynomial::from_y_monomial(&b, n, m); + let poly2 = BivariatePolynomial::new( + vec![ + -b, + Fr::from(0u64), + Fr::from(1u64), + Fr::from(0u64), + Fr::from(0u64), + Fr::from(0u64), + Fr::from(0u64), + Fr::from(0u64), + ], + n, + m, + ); + assert_eq!(poly1.coefficients, poly2.interpolate()); +} + +#[test] +fn test_bi_fft() { + { + let n = 4; + let m = 4; + let poly = BivariatePolynomial::new( + vec![ + Fr::from(1u64), + Fr::from(2u64), + Fr::from(4u64), + Fr::from(8u64), + Fr::from(16u64), + Fr::from(32u64), + Fr::from(64u64), + Fr::from(128u64), + Fr::from(256u64), + Fr::from(128u64), + Fr::from(64u64), + Fr::from(32u64), + Fr::from(16u64), + Fr::from(8u64), + Fr::from(4u64), + Fr::from(2u64), + ], + n, + m, + ); + let mut poly_lag2 = poly.coefficients.clone(); + let poly_lag = poly.interpolate(); + bi_fft_in_place(&mut poly_lag2, n, m); + assert_eq!(poly_lag, poly_lag2); + } + + let mut rng = test_rng(); + + for m in [2, 4, 8, 16, 32, 64].iter() { + for n in [2, 4, 8, 16, 32, 64].iter() { + let poly = BivariatePolynomial::::random(&mut rng, *n, *m); + let mut poly_lag2 = poly.coefficients.clone(); + let poly_lag = poly.evaluate_at_roots(); + bi_fft_in_place(&mut poly_lag2, *n, *m); + assert_eq!(poly_lag, poly_lag2); + } + } +} diff --git a/bi-kzg/src/util.rs b/bi-kzg/src/util.rs index d539b323..49084e90 100644 --- a/bi-kzg/src/util.rs +++ b/bi-kzg/src/util.rs @@ -26,7 +26,7 @@ pub(crate) fn parallelize_internal Vec { let n = v.len(); let num_threads = rayon::current_num_threads(); - let mut chunk = (n as usize) / num_threads; + let mut chunk = n / num_threads; if chunk < num_threads { chunk = 1; }