Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions src/constants.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
pub(crate) const NUM_CHALLENGE_BITS: usize = 128;
pub(crate) const NUM_HASH_BITS: usize = 250;
pub(crate) const BN_LIMB_WIDTH: usize = 64;
pub(crate) const BN_N_LIMBS: usize = 4;
//! This module defines constants used throughout the library.

/// Number of bits used for challenge generation in the protocol.
pub const NUM_CHALLENGE_BITS: usize = 128;

/// Number of bits used for hash output sizing.
pub const NUM_HASH_BITS: usize = 250;

/// Width of each limb in bignat representation.
pub const BN_LIMB_WIDTH: usize = 64;

/// Number of limbs in bignat representation.
pub const BN_N_LIMBS: usize = 4;
9 changes: 9 additions & 0 deletions src/digest.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
//! This module provides digest computation functionality for public parameters.
//!
//! It includes:
//! - `DigestComputer`: A type for computing digests of public parameters.
//! - `Digestible`: A trait for types that can be digested with custom implementations.
//! - `SimpleDigestible`: A marker trait for types that can be digested via serialization.

use crate::constants::NUM_HASH_BITS;
use ff::PrimeField;
use serde::Serialize;
Expand Down Expand Up @@ -26,6 +33,8 @@ impl<T: SimpleDigestible> Digestible for T {
}
}

/// A type for computing digests of public parameters.
/// Uses SHA3-256 and maps the result to a field element.
pub struct DigestComputer<'a, F: PrimeField, T> {
inner: &'a T,
_phantom: PhantomData<F>,
Expand Down
32 changes: 20 additions & 12 deletions src/gadgets/ecc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ use num_bigint::BigInt;
/// `AllocatedPoint` provides an elliptic curve abstraction inside a circuit.
#[derive(Clone)]
pub struct AllocatedPoint<E: Engine> {
pub(crate) x: AllocatedNum<E::Base>,
pub(crate) y: AllocatedNum<E::Base>,
pub(crate) is_infinity: AllocatedNum<E::Base>,
/// The x-coordinate of the point.
pub x: AllocatedNum<E::Base>,
/// The y-coordinate of the point.
pub y: AllocatedNum<E::Base>,
/// Flag indicating if this is the point at infinity (1 = infinity, 0 = not infinity).
pub is_infinity: AllocatedNum<E::Base>,
}

impl<E> AllocatedPoint<E>
Expand Down Expand Up @@ -584,8 +587,10 @@ where
#[derive(Clone)]
/// `AllocatedPoint` but one that is guaranteed to be not infinity
pub struct AllocatedPointNonInfinity<E: Engine> {
x: AllocatedNum<E::Base>,
y: AllocatedNum<E::Base>,
/// The x-coordinate of the point.
pub x: AllocatedNum<E::Base>,
/// The y-coordinate of the point.
pub y: AllocatedNum<E::Base>,
}

impl<E: Engine> AllocatedPointNonInfinity<E> {
Expand Down Expand Up @@ -742,18 +747,21 @@ impl<E: Engine> AllocatedPointNonInfinity<E> {
}
}

// `AllocatedNonnativePoint`s are points on an elliptic curve E'. We use the scalar field
// of another curve E (specified as the group G) to prove things about points on E'.
// `AllocatedNonnativePoint`s are always represented as affine coordinates.
/// `AllocatedNonnativePoint`s are points on an elliptic curve E'. We use the scalar field
/// of another curve E (specified as the group G) to prove things about points on E'.
/// `AllocatedNonnativePoint`s are always represented as affine coordinates.
#[derive(Clone, Debug)]
pub struct AllocatedNonnativePoint<E: Engine> {
pub(crate) x: BigNat<E::Scalar>,
pub(crate) y: BigNat<E::Scalar>,
pub(crate) is_infinity: AllocatedNum<E::Scalar>,
/// The x-coordinate as a BigNat.
pub x: BigNat<E::Scalar>,
/// The y-coordinate as a BigNat.
pub y: BigNat<E::Scalar>,
/// Flag indicating if this is the point at infinity.
pub is_infinity: AllocatedNum<E::Scalar>,
}

#[allow(dead_code)]
impl<E: Engine> AllocatedNonnativePoint<E> {
/// Allocates a new nonnative point from coordinates.
pub fn alloc<CS: ConstraintSystem<E::Scalar>>(
mut cs: CS,
coords: Option<(E::Base, E::Base, bool)>,
Expand Down
12 changes: 9 additions & 3 deletions src/gadgets/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
//! This module implements various gadgets necessary for Nova and applications built with Nova.
pub(crate) mod ecc;
pub(crate) mod nonnative;
pub(crate) mod utils;

/// Elliptic curve gadgets for in-circuit point operations.
pub mod ecc;

/// Non-native field arithmetic gadgets for operations on fields with different characteristics.
pub mod nonnative;

/// Utility gadgets for common operations like conditional selection, bit manipulation, etc.
pub mod utils;
18 changes: 18 additions & 0 deletions src/gadgets/nonnative/bignat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,21 @@ pub fn nat_to_limbs<Scalar: PrimeField>(
}
}

/// Parameters for a `BigNat` representation of a large integer.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BigNatParams {
/// Minimum number of bits required to represent the value.
pub min_bits: usize,
/// Maximum value that a single limb can hold.
pub max_word: BigInt,
/// Number of bits per limb.
pub limb_width: usize,
/// Number of limbs in the representation.
pub n_limbs: usize,
}

impl BigNatParams {
/// Creates a new `BigNatParams` with the specified limb width and number of limbs.
pub fn new(limb_width: usize, n_limbs: usize) -> Self {
let mut max_word = BigInt::from(1) << limb_width as u32;
max_word -= 1;
Expand Down Expand Up @@ -243,6 +249,7 @@ impl<Scalar: PrimeField> BigNat<Scalar> {
Ok(bignat)
}

/// Returns the limbs as a vector of `Num` values.
pub fn as_limbs(&self) -> Vec<Num<Scalar>> {
let mut limbs = Vec::new();
for (i, lc) in self.limbs.iter().enumerate() {
Expand All @@ -254,6 +261,7 @@ impl<Scalar: PrimeField> BigNat<Scalar> {
limbs
}

/// Asserts that the `BigNat` is well-formed by checking that each limb fits in the limb width.
pub fn assert_well_formed<CS: ConstraintSystem<Scalar>>(
&self,
mut cs: CS,
Expand Down Expand Up @@ -309,6 +317,8 @@ impl<Scalar: PrimeField> BigNat<Scalar> {
})
}

/// Enforces that two `BigNat`s have the same limb width.
/// Returns the limb width if they agree, otherwise returns an error.
pub fn enforce_limb_width_agreement(
&self,
other: &Self,
Expand All @@ -325,6 +335,7 @@ impl<Scalar: PrimeField> BigNat<Scalar> {
}
}

/// Constructs a `BigNat` from a polynomial representation.
pub fn from_poly(poly: Polynomial<Scalar>, limb_width: usize, max_word: BigInt) -> Self {
Self {
params: BigNatParams {
Expand Down Expand Up @@ -443,6 +454,7 @@ impl<Scalar: PrimeField> BigNat<Scalar> {
self_grouped.equal_when_carried(cs.namespace(|| "grouped"), &other_grouped)
}

/// Adds two `BigNat`s together, returning a new `BigNat` with the sum.
pub fn add(&self, other: &Self) -> Result<BigNat<Scalar>, SynthesisError> {
self.enforce_limb_width_agreement(other, "add")?;
let n_limbs = max(self.params.n_limbs, other.params.n_limbs);
Expand Down Expand Up @@ -658,18 +670,23 @@ impl<Scalar: PrimeField> BigNat<Scalar> {
}
}

/// Returns the number of bits required to represent the `BigNat`.
pub fn n_bits(&self) -> usize {
assert!(self.params.n_limbs > 0);
self.params.limb_width * (self.params.n_limbs - 1) + self.params.max_word.bits() as usize
}
}

/// A polynomial with coefficients represented as linear combinations.
pub struct Polynomial<Scalar: PrimeField> {
/// The coefficients of the polynomial as linear combinations.
pub coefficients: Vec<LinearCombination<Scalar>>,
/// The concrete values of the coefficients, if available.
pub values: Option<Vec<Scalar>>,
}

impl<Scalar: PrimeField> Polynomial<Scalar> {
/// Allocates constraints for the product of two polynomials.
pub fn alloc_product<CS: ConstraintSystem<Scalar>>(
&self,
mut cs: CS,
Expand Down Expand Up @@ -735,6 +752,7 @@ impl<Scalar: PrimeField> Polynomial<Scalar> {
Ok(product)
}

/// Returns the sum of two polynomials.
pub fn sum(&self, other: &Self) -> Self {
let n_coeffs = max(self.coefficients.len(), other.coefficients.len());
let values = self.values.as_ref().and_then(|self_vs| {
Expand Down
3 changes: 3 additions & 0 deletions src/gadgets/nonnative/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,8 @@ impl<Scalar: PrimeField> BitAccess for Scalar {
}
}

/// Module providing big natural number arithmetic in circuits.
pub mod bignat;

/// Module providing utility types and functions for non-native arithmetic.
pub mod util;
15 changes: 11 additions & 4 deletions src/gadgets/nonnative/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ use std::{
#[derive(Clone)]
/// A representation of a bit
pub struct Bit<Scalar: PrimeField> {
/// The linear combination which constrain the value of the bit
/// The linear combination which constrains the value of the bit
pub bit: LinearCombination<Scalar>,
}

#[derive(Clone)]
/// A representation of a bit-vector
pub struct Bitvector<Scalar: PrimeField> {
/// The linear combination which constrain the values of the bits
/// The linear combination which constrains the values of the bits
pub bits: Vec<LinearCombination<Scalar>>,
/// The value of the bits (filled at witness-time)
pub values: Option<Vec<bool>>,
Expand Down Expand Up @@ -61,15 +61,20 @@ impl<Scalar: PrimeField> Bit<Scalar> {
}
}

/// A representation of a field element as a linear combination with an optional value.
pub struct Num<Scalar: PrimeField> {
pub(crate) num: LinearCombination<Scalar>,
pub(crate) value: Option<Scalar>,
/// The linear combination representing the number.
pub num: LinearCombination<Scalar>,
/// The value of the number (filled at witness-time).
pub value: Option<Scalar>,
}

impl<Scalar: PrimeField> Num<Scalar> {
/// Creates a new `Num` with the given value and linear combination.
pub const fn new(value: Option<Scalar>, num: LinearCombination<Scalar>) -> Self {
Self { value, num }
}
/// Allocates a new `Num` in the constraint system with the given value.
pub fn alloc<CS, F>(mut cs: CS, value: F) -> Result<Self, SynthesisError>
where
CS: ConstraintSystem<Scalar>,
Expand All @@ -93,6 +98,7 @@ impl<Scalar: PrimeField> Num<Scalar> {
})
}

/// Checks that the `Num` fits in the given number of bits.
pub fn fits_in_bits<CS: ConstraintSystem<Scalar>>(
&self,
mut cs: CS,
Expand Down Expand Up @@ -211,6 +217,7 @@ impl<Scalar: PrimeField> Num<Scalar> {
})
}

/// Converts the `Num` to an `AllocatedNum` in the constraint system.
pub fn as_allocated_num<CS: ConstraintSystem<Scalar>>(
&self,
mut cs: CS,
Expand Down
8 changes: 3 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,16 @@ pub mod nova;
pub mod neutron;

// public modules
pub mod constants;
pub mod digest;
pub mod errors;
pub mod frontend;
pub mod gadgets;
pub mod provider;
pub mod r1cs;
pub mod spartan;
pub mod traits;

// private modules
mod constants;
mod digest;
mod r1cs;

use traits::{commitment::CommitmentEngineTrait, Engine};

// some type aliases
Expand Down
2 changes: 1 addition & 1 deletion src/nova/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use rand_core::OsRng;
use serde::{Deserialize, Serialize};

mod circuit;
pub(crate) mod nifs;
pub mod nifs;

use circuit::{NovaAugmentedCircuit, NovaAugmentedCircuitInputs};
use nifs::{NIFSRelaxed, NIFS};
Expand Down
21 changes: 21 additions & 0 deletions src/provider/hyperkzg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,23 @@ where
pub fn tau_H(&self) -> &<<E::GE as PairingGroup>::G2 as DlogGroup>::AffineGroupElement {
&self.tau_H
}

/// Returns the coordinates of the generator points.
///
/// # Panics
///
/// Panics if any generator point is the point at infinity.
pub fn to_coordinates(&self) -> Vec<(E::Base, E::Base)> {
self
.ck
.iter()
.map(|c| {
let (x, y, is_infinity) = <E::GE as DlogGroup>::group(c).to_coordinates();
assert!(!is_infinity);
(x, y)
})
.collect()
}
}

impl<E: Engine> Len for CommitmentKey<E>
Expand Down Expand Up @@ -580,6 +597,10 @@ where

Commitment { comm: res }
}

fn ck_to_coordinates(ck: &Self::CommitmentKey) -> Vec<(E::Base, E::Base)> {
ck.to_coordinates()
}
}

/// Provides an implementation of generators for proving evaluations
Expand Down
1 change: 1 addition & 0 deletions src/provider/mercury.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ impl<Scalar: PrimeField> UniPoly<Scalar> {
self.coeffs.resize(size, Scalar::ZERO);
}

/// Scales all coefficients of the polynomial by a scalar value.
pub fn scale(&mut self, s: &Scalar) {
self.coeffs.par_iter_mut().for_each(|c| *c *= *s);
}
Expand Down
25 changes: 25 additions & 0 deletions src/provider/pedersen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,27 @@ where
points.extend(self.ck.iter().cloned());
write_points(writer, points)
}

/// Returns the coordinates of the generator points.
///
/// This method extracts the (x, y) coordinates of each generator point
/// in the commitment key. This is useful for operations that need direct
/// access to the underlying elliptic curve points.
///
/// # Panics
///
/// Panics if any generator point is the point at infinity.
pub fn to_coordinates(&self) -> Vec<(E::Base, E::Base)> {
self
.ck
.iter()
.map(|c| {
let (x, y, is_infinity) = <E::GE as DlogGroup>::group(c).to_coordinates();
assert!(!is_infinity);
(x, y)
})
.collect()
}
}

impl<E: Engine> CommitmentEngineTrait<E> for CommitmentEngine<E>
Expand Down Expand Up @@ -301,6 +322,10 @@ where
h: first[0],
})
}

fn ck_to_coordinates(ck: &Self::CommitmentKey) -> Vec<(E::Base, E::Base)> {
ck.to_coordinates()
}
}

/// A trait listing properties of a commitment key that can be managed in a divide-and-conquer fashion
Expand Down
Loading
Loading