mirror of
https://github.com/arnaucube/sonobe.git
synced 2026-01-12 00:41:28 +01:00
Add utils::vec & pedersen modules (#5)
- utils::vec module: port a mix of vec utils from nova-study, multifolding-poc and protogalaxy-poc repos - pedersen.rs: Pedersen commitment module - other: - update FoldingScheme trait interface: rm rng, update internal types naming as agreed in today's call - update Cargo.toml dev-dependencies imports, since bn254 - grumpkin is not ready yet, use bls12-377 - bw6-761 curve cycle - transcript module: add absorb_point method
This commit is contained in:
@@ -14,7 +14,8 @@ ark-r1cs-std = { version = "^0.4.0", default-features = false }
|
|||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
ark-bls12-381 = "0.4.0"
|
ark-bls12-377 = "0.4.0"
|
||||||
|
ark-bw6-761 = "0.4.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
|||||||
24
src/lib.rs
24
src/lib.rs
@@ -8,6 +8,8 @@ use thiserror::Error;
|
|||||||
|
|
||||||
pub mod transcript;
|
pub mod transcript;
|
||||||
use transcript::Transcript;
|
use transcript::Transcript;
|
||||||
|
pub mod pedersen;
|
||||||
|
pub mod utils;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@@ -19,23 +21,21 @@ pub enum Error {
|
|||||||
/// over a cycle of curves (C1, C2), where:
|
/// over a cycle of curves (C1, C2), where:
|
||||||
/// - C1 is the main curve, which ScalarField we use as our F for al the field operations
|
/// - C1 is the main curve, which ScalarField we use as our F for al the field operations
|
||||||
/// - C2 is the auxiliary curve, which we use for the commitments, whose BaseField (for point
|
/// - C2 is the auxiliary curve, which we use for the commitments, whose BaseField (for point
|
||||||
/// coordinates) are in the C1::ScalarField
|
/// coordinates) are in the C1::ScalarField.
|
||||||
|
/// In other words, C1.Fq == C2.Fr, and C1.Fr == C2.Fq.
|
||||||
pub trait FoldingScheme<C1: CurveGroup, C2: CurveGroup>: Clone + Debug
|
pub trait FoldingScheme<C1: CurveGroup, C2: CurveGroup>: Clone + Debug
|
||||||
where
|
where
|
||||||
C1: CurveGroup<BaseField = C2::ScalarField, ScalarField = C2::BaseField>,
|
C1: CurveGroup<BaseField = C2::ScalarField, ScalarField = C2::BaseField>,
|
||||||
C2::BaseField: PrimeField,
|
C2::BaseField: PrimeField,
|
||||||
{
|
{
|
||||||
// type PCS: PolynomialCommitmentScheme<C>; // maybe not needed, just PedersenCommitment
|
|
||||||
type PreprocessorParam: Debug;
|
type PreprocessorParam: Debug;
|
||||||
type ProverParam: Debug;
|
type ProverParam: Debug;
|
||||||
type VerifierParam: Debug;
|
type VerifierParam: Debug;
|
||||||
type FreshInstance: Debug;
|
type Witness: Debug;
|
||||||
type PublicInput: Debug;
|
|
||||||
type CommittedInstanceWithWitness: Debug;
|
type CommittedInstanceWithWitness: Debug;
|
||||||
type CommittedInstance: Clone + Debug;
|
type CommittedInstance: Clone + Debug;
|
||||||
|
|
||||||
fn preprocess(
|
fn preprocess(
|
||||||
// pcs_param: &<Self::CS as PolynomialCommitmentScheme<C>>::Param,
|
|
||||||
prep_param: &Self::PreprocessorParam,
|
prep_param: &Self::PreprocessorParam,
|
||||||
) -> Result<(Self::ProverParam, Self::VerifierParam), Error>;
|
) -> Result<(Self::ProverParam, Self::VerifierParam), Error>;
|
||||||
|
|
||||||
@@ -46,17 +46,15 @@ where
|
|||||||
fn prove(
|
fn prove(
|
||||||
pp: &Self::ProverParam,
|
pp: &Self::ProverParam,
|
||||||
running_instance: &mut Self::CommittedInstanceWithWitness,
|
running_instance: &mut Self::CommittedInstanceWithWitness,
|
||||||
incomming_instances: &[Self::FreshInstance],
|
incomming_instances: &[Self::Witness],
|
||||||
transcript: &mut impl Transcript<C1::ScalarField>,
|
transcript: &mut impl Transcript<C1>,
|
||||||
rng: impl RngCore,
|
|
||||||
) -> Result<(), Error>;
|
) -> Result<(), Error>;
|
||||||
|
|
||||||
fn verify(
|
fn verify(
|
||||||
vp: &Self::VerifierParam,
|
vp: &Self::VerifierParam,
|
||||||
running_instance: &mut Self::CommittedInstance,
|
running_instance: &mut Self::CommittedInstance,
|
||||||
incomming_instances: &[Self::PublicInput],
|
incomming_instances: &[Self::CommittedInstance],
|
||||||
transcript: &mut impl Transcript<C1::ScalarField>,
|
transcript: &mut impl Transcript<C1>,
|
||||||
rng: impl RngCore,
|
|
||||||
) -> Result<(), Error>;
|
) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,14 +70,14 @@ pub trait Decider<C: CurveGroup>: Clone + Debug {
|
|||||||
fn prove(
|
fn prove(
|
||||||
pp: &Self::ProverParam,
|
pp: &Self::ProverParam,
|
||||||
running_instance: &Self::CommittedInstanceWithWitness,
|
running_instance: &Self::CommittedInstanceWithWitness,
|
||||||
transcript: &mut impl Transcript<C::ScalarField>,
|
transcript: &mut impl Transcript<C>,
|
||||||
rng: impl RngCore,
|
rng: impl RngCore,
|
||||||
) -> Result<(), Error>;
|
) -> Result<(), Error>;
|
||||||
|
|
||||||
fn verify(
|
fn verify(
|
||||||
vp: &Self::VerifierParam,
|
vp: &Self::VerifierParam,
|
||||||
running_instance: &Self::CommittedInstance,
|
running_instance: &Self::CommittedInstance,
|
||||||
transcript: &mut impl Transcript<C::ScalarField>,
|
transcript: &mut impl Transcript<C>,
|
||||||
rng: impl RngCore,
|
rng: impl RngCore,
|
||||||
) -> Result<(), Error>;
|
) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
|||||||
127
src/pedersen.rs
Normal file
127
src/pedersen.rs
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
use ark_ec::{CurveGroup, Group};
|
||||||
|
use ark_std::{rand::Rng, UniformRand};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
use crate::utils::vec::{vec_add, vec_scalar_mul};
|
||||||
|
|
||||||
|
use crate::transcript::Transcript;
|
||||||
|
use ark_crypto_primitives::sponge::Absorb;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
pub struct Proof<C: CurveGroup> {
|
||||||
|
R: C,
|
||||||
|
u: Vec<C::ScalarField>,
|
||||||
|
r_u: C::ScalarField,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
pub struct Params<C: CurveGroup> {
|
||||||
|
h: C,
|
||||||
|
pub generators: Vec<C::Affine>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
pub struct Pedersen<C: CurveGroup>
|
||||||
|
where
|
||||||
|
<C as Group>::ScalarField: Absorb,
|
||||||
|
{
|
||||||
|
_c: PhantomData<C>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C: CurveGroup> Pedersen<C>
|
||||||
|
where
|
||||||
|
<C as Group>::ScalarField: Absorb,
|
||||||
|
{
|
||||||
|
pub fn new_params<R: Rng>(rng: &mut R, max: usize) -> Params<C> {
|
||||||
|
let generators: Vec<C::Affine> = std::iter::repeat_with(|| C::Affine::rand(rng))
|
||||||
|
.take(max.next_power_of_two())
|
||||||
|
.collect();
|
||||||
|
let params: Params<C> = Params::<C> {
|
||||||
|
h: C::rand(rng),
|
||||||
|
generators,
|
||||||
|
};
|
||||||
|
params
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn commit(params: &Params<C>, v: &Vec<C::ScalarField>, r: &C::ScalarField) -> C {
|
||||||
|
// h⋅r + <g, v>
|
||||||
|
params.h.mul(r) + C::msm(¶ms.generators[..v.len()], v).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prove(
|
||||||
|
params: &Params<C>,
|
||||||
|
transcript: &mut impl Transcript<C>,
|
||||||
|
cm: &C,
|
||||||
|
v: &Vec<C::ScalarField>,
|
||||||
|
r: &C::ScalarField,
|
||||||
|
) -> Proof<C> {
|
||||||
|
transcript.absorb_point(cm);
|
||||||
|
let r1 = transcript.get_challenge();
|
||||||
|
let d = transcript.get_challenges(v.len());
|
||||||
|
|
||||||
|
// R = h⋅r_1 + <g, d>
|
||||||
|
let R: C = params.h.mul(r1) + C::msm(¶ms.generators[..d.len()], &d).unwrap();
|
||||||
|
|
||||||
|
transcript.absorb_point(&R);
|
||||||
|
let e = transcript.get_challenge();
|
||||||
|
|
||||||
|
// u = d + v⋅e
|
||||||
|
let u = vec_add(&vec_scalar_mul(v, &e), &d);
|
||||||
|
// r_u = e⋅r + r_1
|
||||||
|
let r_u = e * r + r1;
|
||||||
|
|
||||||
|
Proof::<C> { R, u, r_u }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify(
|
||||||
|
params: &Params<C>,
|
||||||
|
transcript: &mut impl Transcript<C>,
|
||||||
|
cm: C,
|
||||||
|
proof: Proof<C>,
|
||||||
|
) -> bool {
|
||||||
|
transcript.absorb_point(&cm);
|
||||||
|
transcript.get_challenge(); // r_1
|
||||||
|
transcript.get_challenges(proof.u.len()); // d
|
||||||
|
transcript.absorb_point(&proof.R);
|
||||||
|
let e = transcript.get_challenge();
|
||||||
|
|
||||||
|
// check that: R + cm == h⋅r_u + <g, u>
|
||||||
|
let lhs = proof.R + cm.mul(e);
|
||||||
|
let rhs = params.h.mul(proof.r_u)
|
||||||
|
+ C::msm(¶ms.generators[..proof.u.len()], &proof.u).unwrap();
|
||||||
|
if lhs != rhs {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::transcript::poseidon::{tests::poseidon_test_config, PoseidonTranscript};
|
||||||
|
|
||||||
|
use ark_bls12_377::{Fr, G1Projective};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_pedersen_vector() {
|
||||||
|
let mut rng = ark_std::test_rng();
|
||||||
|
|
||||||
|
const n: usize = 10;
|
||||||
|
// setup params
|
||||||
|
let params = Pedersen::<G1Projective>::new_params(&mut rng, n);
|
||||||
|
let poseidon_config = poseidon_test_config::<Fr>();
|
||||||
|
|
||||||
|
// init Prover's transcript
|
||||||
|
let mut transcript_p = PoseidonTranscript::<G1Projective>::new(&poseidon_config);
|
||||||
|
// init Verifier's transcript
|
||||||
|
let mut transcript_v = PoseidonTranscript::<G1Projective>::new(&poseidon_config);
|
||||||
|
|
||||||
|
let v: Vec<Fr> = vec![Fr::rand(&mut rng); n];
|
||||||
|
let r: Fr = Fr::rand(&mut rng);
|
||||||
|
let cm = Pedersen::<G1Projective>::commit(¶ms, &v, &r);
|
||||||
|
let proof = Pedersen::<G1Projective>::prove(¶ms, &mut transcript_p, &cm, &v, &r);
|
||||||
|
let v = Pedersen::<G1Projective>::verify(¶ms, &mut transcript_v, cm, proof);
|
||||||
|
assert!(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
use ark_ff::PrimeField;
|
use ark_ec::CurveGroup;
|
||||||
use ark_std::fmt::Debug;
|
use ark_std::fmt::Debug;
|
||||||
|
|
||||||
pub mod poseidon;
|
pub mod poseidon;
|
||||||
|
|
||||||
pub trait Transcript<F: PrimeField> {
|
pub trait Transcript<C: CurveGroup> {
|
||||||
type TranscriptConfig: Debug;
|
type TranscriptConfig: Debug;
|
||||||
|
|
||||||
fn new(config: &Self::TranscriptConfig) -> Self;
|
fn new(config: &Self::TranscriptConfig) -> Self;
|
||||||
fn absorb(&mut self, v: &F);
|
fn absorb(&mut self, v: &C::ScalarField);
|
||||||
fn absorb_vec(&mut self, v: &[F]);
|
fn absorb_vec(&mut self, v: &[C::ScalarField]);
|
||||||
fn get_challenge(&mut self) -> F;
|
fn absorb_point(&mut self, v: &C);
|
||||||
fn get_challenges(&mut self, n: usize) -> Vec<F>;
|
fn get_challenge(&mut self) -> C::ScalarField;
|
||||||
|
fn get_challenges(&mut self, n: usize) -> Vec<C::ScalarField>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,42 +3,75 @@ use ark_crypto_primitives::sponge::{
|
|||||||
poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig, PoseidonSponge},
|
poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig, PoseidonSponge},
|
||||||
Absorb, CryptographicSponge,
|
Absorb, CryptographicSponge,
|
||||||
};
|
};
|
||||||
use ark_ff::PrimeField;
|
use ark_ec::{AffineRepr, CurveGroup, Group};
|
||||||
|
use ark_ff::{BigInteger, Field, PrimeField};
|
||||||
use ark_r1cs_std::fields::fp::FpVar;
|
use ark_r1cs_std::fields::fp::FpVar;
|
||||||
use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError};
|
use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError};
|
||||||
|
|
||||||
use crate::transcript::Transcript;
|
use crate::transcript::Transcript;
|
||||||
|
|
||||||
/// PoseidonTranscript implements the Transcript trait using the Poseidon hash
|
/// PoseidonTranscript implements the Transcript trait using the Poseidon hash
|
||||||
pub struct PoseidonTranscript<F: PrimeField + Absorb> {
|
pub struct PoseidonTranscript<C: CurveGroup>
|
||||||
sponge: PoseidonSponge<F>,
|
where
|
||||||
|
<C as Group>::ScalarField: Absorb,
|
||||||
|
{
|
||||||
|
sponge: PoseidonSponge<C::ScalarField>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: PrimeField + Absorb> Transcript<F> for PoseidonTranscript<F> {
|
impl<C: CurveGroup> Transcript<C> for PoseidonTranscript<C>
|
||||||
type TranscriptConfig = PoseidonConfig<F>;
|
where
|
||||||
|
<C as Group>::ScalarField: Absorb,
|
||||||
|
{
|
||||||
|
type TranscriptConfig = PoseidonConfig<C::ScalarField>;
|
||||||
|
|
||||||
fn new(poseidon_config: &Self::TranscriptConfig) -> Self {
|
fn new(poseidon_config: &Self::TranscriptConfig) -> Self {
|
||||||
let sponge = PoseidonSponge::<F>::new(poseidon_config);
|
let sponge = PoseidonSponge::<C::ScalarField>::new(poseidon_config);
|
||||||
Self { sponge }
|
Self { sponge }
|
||||||
}
|
}
|
||||||
fn absorb(&mut self, v: &F) {
|
fn absorb(&mut self, v: &C::ScalarField) {
|
||||||
self.sponge.absorb(&v);
|
self.sponge.absorb(&v);
|
||||||
}
|
}
|
||||||
fn absorb_vec(&mut self, v: &[F]) {
|
fn absorb_vec(&mut self, v: &[C::ScalarField]) {
|
||||||
self.sponge.absorb(&v);
|
self.sponge.absorb(&v);
|
||||||
}
|
}
|
||||||
fn get_challenge(&mut self) -> F {
|
fn absorb_point(&mut self, p: &C) {
|
||||||
|
self.sponge.absorb(&prepare_point(p));
|
||||||
|
}
|
||||||
|
fn get_challenge(&mut self) -> C::ScalarField {
|
||||||
let c = self.sponge.squeeze_field_elements(1);
|
let c = self.sponge.squeeze_field_elements(1);
|
||||||
self.sponge.absorb(&c[0]);
|
self.sponge.absorb(&c[0]);
|
||||||
c[0]
|
c[0]
|
||||||
}
|
}
|
||||||
fn get_challenges(&mut self, n: usize) -> Vec<F> {
|
fn get_challenges(&mut self, n: usize) -> Vec<C::ScalarField> {
|
||||||
let c = self.sponge.squeeze_field_elements(n);
|
let c = self.sponge.squeeze_field_elements(n);
|
||||||
self.sponge.absorb(&c);
|
self.sponge.absorb(&c);
|
||||||
c
|
c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the point coordinates in Fr, so it can be absrobed by the transcript. It does not work
|
||||||
|
// over bytes in order to have a logic that can be reproduced in-circuit.
|
||||||
|
fn prepare_point<C: CurveGroup>(p: &C) -> Vec<C::ScalarField> {
|
||||||
|
let binding = p.into_affine();
|
||||||
|
let p_coords = &binding.xy().unwrap();
|
||||||
|
let x_bi = p_coords
|
||||||
|
.0
|
||||||
|
.to_base_prime_field_elements()
|
||||||
|
.next()
|
||||||
|
.expect("a")
|
||||||
|
.into_bigint();
|
||||||
|
let y_bi = p_coords
|
||||||
|
.1
|
||||||
|
.to_base_prime_field_elements()
|
||||||
|
.next()
|
||||||
|
.expect("a")
|
||||||
|
.into_bigint();
|
||||||
|
vec![
|
||||||
|
C::ScalarField::from_le_bytes_mod_order(x_bi.to_bytes_le().as_ref()),
|
||||||
|
C::ScalarField::from_le_bytes_mod_order(y_bi.to_bytes_le().as_ref()),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
/// PoseidonTranscriptVar implements the gadget compatible with PoseidonTranscript
|
/// PoseidonTranscriptVar implements the gadget compatible with PoseidonTranscript
|
||||||
pub struct PoseidonTranscriptVar<F: PrimeField> {
|
pub struct PoseidonTranscriptVar<F: PrimeField> {
|
||||||
sponge: PoseidonSpongeVar<F>,
|
sponge: PoseidonSpongeVar<F>,
|
||||||
@@ -67,9 +100,9 @@ impl<F: PrimeField> PoseidonTranscriptVar<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
pub mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use ark_bls12_381::Fr;
|
use ark_bls12_377::{Fr, G1Projective};
|
||||||
use ark_crypto_primitives::sponge::poseidon::find_poseidon_ark_and_mds;
|
use ark_crypto_primitives::sponge::poseidon::find_poseidon_ark_and_mds;
|
||||||
use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar, R1CSVar};
|
use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar, R1CSVar};
|
||||||
use ark_relations::r1cs::ConstraintSystem;
|
use ark_relations::r1cs::ConstraintSystem;
|
||||||
@@ -105,7 +138,7 @@ mod tests {
|
|||||||
fn test_transcript_and_transcriptvar() {
|
fn test_transcript_and_transcriptvar() {
|
||||||
// use 'native' transcript
|
// use 'native' transcript
|
||||||
let config = poseidon_test_config::<Fr>();
|
let config = poseidon_test_config::<Fr>();
|
||||||
let mut tr = PoseidonTranscript::<Fr>::new(&config);
|
let mut tr = PoseidonTranscript::<G1Projective>::new(&config);
|
||||||
tr.absorb(&Fr::from(42_u32));
|
tr.absorb(&Fr::from(42_u32));
|
||||||
let c = tr.get_challenge();
|
let c = tr.get_challenge();
|
||||||
|
|
||||||
|
|||||||
1
src/utils/mod.rs
Normal file
1
src/utils/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod vec;
|
||||||
86
src/utils/vec.rs
Normal file
86
src/utils/vec.rs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
use ark_ff::PrimeField;
|
||||||
|
use ark_std::cfg_iter;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub struct SparseMatrix<F: PrimeField> {
|
||||||
|
pub n_rows: usize,
|
||||||
|
pub n_cols: usize,
|
||||||
|
pub coeffs: Vec<(usize, usize, F)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dense_matrix_to_sparse<F: PrimeField>(m: Vec<Vec<F>>) -> SparseMatrix<F> {
|
||||||
|
let mut r = SparseMatrix::<F> {
|
||||||
|
n_rows: m.len(),
|
||||||
|
n_cols: m[0].len(),
|
||||||
|
coeffs: Vec::new(),
|
||||||
|
};
|
||||||
|
for (i, m_i) in m.iter().enumerate() {
|
||||||
|
for (j, m_ij) in m_i.iter().enumerate() {
|
||||||
|
if !m_ij.is_zero() {
|
||||||
|
r.coeffs.push((i, j, *m_ij));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn vec_add<F: PrimeField>(a: &[F], b: &[F]) -> Vec<F> {
|
||||||
|
assert_eq!(a.len(), b.len());
|
||||||
|
let mut r: Vec<F> = vec![F::zero(); a.len()];
|
||||||
|
for i in 0..a.len() {
|
||||||
|
r[i] = a[i] + b[i];
|
||||||
|
}
|
||||||
|
r
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn vec_sub<F: PrimeField>(a: &[F], b: &[F]) -> Vec<F> {
|
||||||
|
assert_eq!(a.len(), b.len());
|
||||||
|
let mut r: Vec<F> = vec![F::zero(); a.len()];
|
||||||
|
for i in 0..a.len() {
|
||||||
|
r[i] = a[i] - b[i];
|
||||||
|
}
|
||||||
|
r
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn vec_scalar_mul<F: PrimeField>(vec: &[F], c: &F) -> Vec<F> {
|
||||||
|
let mut result = vec![F::zero(); vec.len()];
|
||||||
|
for (i, a) in vec.iter().enumerate() {
|
||||||
|
result[i] = *a * c;
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_zero_vec<F: PrimeField>(vec: &[F]) -> bool {
|
||||||
|
for e in vec {
|
||||||
|
if !e.is_zero() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mat_vec_mul<F: PrimeField>(M: &Vec<Vec<F>>, z: &[F]) -> Vec<F> {
|
||||||
|
assert!(!M.is_empty());
|
||||||
|
assert_eq!(M[0].len(), z.len());
|
||||||
|
|
||||||
|
let mut r: Vec<F> = vec![F::zero(); M.len()];
|
||||||
|
for (i, M_i) in M.iter().enumerate() {
|
||||||
|
for (j, M_ij) in M_i.iter().enumerate() {
|
||||||
|
r[i] += *M_ij * z[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mat_vec_mul_sparse<F: PrimeField>(matrix: &SparseMatrix<F>, vector: &[F]) -> Vec<F> {
|
||||||
|
let mut res = vec![F::zero(); matrix.n_cols];
|
||||||
|
for &(row, col, value) in matrix.coeffs.iter() {
|
||||||
|
res[row] += value * vector[col];
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hadamard<F: PrimeField>(a: &[F], b: &[F]) -> Vec<F> {
|
||||||
|
assert_eq!(a.len(), b.len());
|
||||||
|
cfg_iter!(a).zip(b).map(|(a, b)| *a * b).collect()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user