Skip to content

Commit

Permalink
refactor: Refactor main Group trait to use group::Group
Browse files Browse the repository at this point in the history
- the main Group trait now uses ::zkcrypto::group::Group
- Refactored the usage of generic type associated 'Scalar' across multiple files and functions from 'G::Scalar' to fully qualified '<G as Group>::Scalar'.
- No new features were added, functionality remained the same, changes were mostly aimed at improving type inference and handling.
  • Loading branch information
huitseeker committed Jul 21, 2023
1 parent b2eb8ca commit 5ee0590
Show file tree
Hide file tree
Showing 26 changed files with 807 additions and 651 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ bitvec = "1.0"
byteorder = "1.4.3"
thiserror = "1.0"
halo2curves = { version = "0.1.0", features = ["derive_serde"] }
group = "0.13.0"

[target.'cfg(any(target_arch = "x86_64", target_arch = "aarch64"))'.dependencies]
pasta-msm = { version = "0.1.4" }
Expand Down
35 changes: 19 additions & 16 deletions examples/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ use rand::{rngs::OsRng, RngCore};
use sha3::{Digest, Sha3_512};

#[derive(Debug, Clone, Copy)]
pub struct SecretKey<G: Group>(G::Scalar);
pub struct SecretKey<G: Group>(<G as Group>::Scalar);

impl<G> SecretKey<G>
where
G: Group,
{
pub fn random(mut rng: impl RngCore) -> Self {
let secret = G::Scalar::random(&mut rng);
let secret = <G as Group>::Scalar::random(&mut rng);
Self(secret)
}
}
Expand All @@ -45,14 +45,14 @@ where
#[derive(Clone)]
pub struct Signature<G: Group> {
pub r: G,
pub s: G::Scalar,
pub s: <G as Group>::Scalar,
}

impl<G> SecretKey<G>
where
G: Group,
{
pub fn sign(self, c: G::Scalar, mut rng: impl RngCore) -> Signature<G> {
pub fn sign(self, c: <G as Group>::Scalar, mut rng: impl RngCore) -> Signature<G> {
// T
let mut t = [0u8; 80];
rng.fill_bytes(&mut t[..]);
Expand All @@ -72,8 +72,11 @@ where
Signature { r, s }
}

fn mul_bits<B: AsRef<[u64]>>(s: &G::Scalar, bits: BitIterator<B>) -> G::Scalar {
let mut x = G::Scalar::ZERO;
fn mul_bits<B: AsRef<[u64]>>(
s: &<G as Group>::Scalar,
bits: BitIterator<B>,
) -> <G as Group>::Scalar {
let mut x = <G as Group>::Scalar::ZERO;
for bit in bits {
x = x.double();

Expand All @@ -84,21 +87,21 @@ where
x
}

fn to_uniform(digest: &[u8]) -> G::Scalar {
fn to_uniform(digest: &[u8]) -> <G as Group>::Scalar {
assert_eq!(digest.len(), 64);
let mut bits: [u64; 8] = [0; 8];
LittleEndian::read_u64_into(digest, &mut bits);
Self::mul_bits(&G::Scalar::ONE, BitIterator::new(bits))
Self::mul_bits(&<G as Group>::Scalar::ONE, BitIterator::new(bits))
}

pub fn to_uniform_32(digest: &[u8]) -> G::Scalar {
pub fn to_uniform_32(digest: &[u8]) -> <G as Group>::Scalar {
assert_eq!(digest.len(), 32);
let mut bits: [u64; 4] = [0; 4];
LittleEndian::read_u64_into(digest, &mut bits);
Self::mul_bits(&G::Scalar::ONE, BitIterator::new(bits))
Self::mul_bits(&<G as Group>::Scalar::ONE, BitIterator::new(bits))
}

pub fn hash_to_scalar(persona: &[u8], a: &[u8], b: &[u8]) -> G::Scalar {
pub fn hash_to_scalar(persona: &[u8], a: &[u8], b: &[u8]) -> <G as Group>::Scalar {
let mut hasher = Sha3_512::new();
hasher.update(persona);
hasher.update(a);
Expand All @@ -111,9 +114,9 @@ where
impl<G> PublicKey<G>
where
G: Group,
G::Scalar: PrimeFieldBits,
<G as Group>::Scalar: PrimeFieldBits,
{
pub fn verify(&self, c: G::Scalar, signature: &Signature<G>) -> bool {
pub fn verify(&self, c: <G as Group>::Scalar, signature: &Signature<G>) -> bool {
let modulus = Self::modulus_as_scalar();
let order_check_pk = self.0.mul(modulus);
if !order_check_pk.eq(&G::identity()) {
Expand All @@ -134,15 +137,15 @@ where
.eq(&G::identity())
}

fn modulus_as_scalar() -> G::Scalar {
let mut bits = G::Scalar::char_le_bits().to_bitvec();
fn modulus_as_scalar() -> <G as Group>::Scalar {
let mut bits = <G as Group>::Scalar::char_le_bits().to_bitvec();
let mut acc = BigUint::new(Vec::<u32>::new());
while let Some(b) = bits.pop() {
acc <<= 1_i32;
acc += b as u8;
}
let modulus = acc.to_str_radix(10);
G::Scalar::from_str_vartime(&modulus).unwrap()
<G as Group>::Scalar::from_str_vartime(&modulus).unwrap()
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/bellperson/r1cs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ impl<G: Group> NovaWitness<G> for SatisfyingAssignment<G> {

impl<G: Group> NovaShape<G> for ShapeCS<G> {
fn r1cs_shape(&self) -> (R1CSShape<G>, CommitmentKey<G>) {
let mut A: Vec<(usize, usize, G::Scalar)> = Vec::new();
let mut B: Vec<(usize, usize, G::Scalar)> = Vec::new();
let mut C: Vec<(usize, usize, G::Scalar)> = Vec::new();
let mut A: Vec<(usize, usize, <G as Group>::Scalar)> = Vec::new();
let mut B: Vec<(usize, usize, <G as Group>::Scalar)> = Vec::new();
let mut C: Vec<(usize, usize, <G as Group>::Scalar)> = Vec::new();

let mut num_cons_added = 0;
let mut X = (&mut A, &mut B, &mut C, &mut num_cons_added);
Expand Down
30 changes: 15 additions & 15 deletions src/bellperson/shape_cs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ pub struct ShapeCS<G: Group> {
#[allow(clippy::type_complexity)]
/// All constraints added to the `ShapeCS`.
pub constraints: Vec<(
LinearCombination<G::Scalar>,
LinearCombination<G::Scalar>,
LinearCombination<G::Scalar>,
LinearCombination<<G as Group>::Scalar>,
LinearCombination<<G as Group>::Scalar>,
LinearCombination<<G as Group>::Scalar>,
String,
)>,
inputs: Vec<String>,
Expand Down Expand Up @@ -138,24 +138,24 @@ impl<G: Group> ShapeCS<G> {
writeln!(s, "INPUT {}", &input).unwrap()
}

let negone = -<G::Scalar>::ONE;
let negone = -<<G as Group>::Scalar>::ONE;

let powers_of_two = (0..G::Scalar::NUM_BITS)
.map(|i| G::Scalar::from(2u64).pow_vartime([u64::from(i)]))
let powers_of_two = (0..<G as Group>::Scalar::NUM_BITS)
.map(|i| <G as Group>::Scalar::from(2u64).pow_vartime([u64::from(i)]))
.collect::<Vec<_>>();

let pp = |s: &mut String, lc: &LinearCombination<G::Scalar>| {
let pp = |s: &mut String, lc: &LinearCombination<<G as Group>::Scalar>| {
s.push('(');
let mut is_first = true;
for (var, coeff) in proc_lc::<G::Scalar>(lc) {
for (var, coeff) in proc_lc::<<G as Group>::Scalar>(lc) {
if coeff == negone {
s.push_str(" - ")
} else if !is_first {
s.push_str(" + ")
}
is_first = false;

if coeff != <G::Scalar>::ONE && coeff != negone {
if coeff != <<G as Group>::Scalar>::ONE && coeff != negone {
for (i, x) in powers_of_two.iter().enumerate() {
if x == &coeff {
write!(s, "2^{i} . ").unwrap();
Expand Down Expand Up @@ -224,12 +224,12 @@ impl<G: Group> Default for ShapeCS<G> {
}
}

impl<G: Group> ConstraintSystem<G::Scalar> for ShapeCS<G> {
impl<G: Group> ConstraintSystem<<G as Group>::Scalar> for ShapeCS<G> {
type Root = Self;

fn alloc<F, A, AR>(&mut self, annotation: A, _f: F) -> Result<Variable, SynthesisError>
where
F: FnOnce() -> Result<G::Scalar, SynthesisError>,
F: FnOnce() -> Result<<G as Group>::Scalar, SynthesisError>,
A: FnOnce() -> AR,
AR: Into<String>,
{
Expand All @@ -241,7 +241,7 @@ impl<G: Group> ConstraintSystem<G::Scalar> for ShapeCS<G> {

fn alloc_input<F, A, AR>(&mut self, annotation: A, _f: F) -> Result<Variable, SynthesisError>
where
F: FnOnce() -> Result<G::Scalar, SynthesisError>,
F: FnOnce() -> Result<<G as Group>::Scalar, SynthesisError>,
A: FnOnce() -> AR,
AR: Into<String>,
{
Expand All @@ -255,9 +255,9 @@ impl<G: Group> ConstraintSystem<G::Scalar> for ShapeCS<G> {
where
A: FnOnce() -> AR,
AR: Into<String>,
LA: FnOnce(LinearCombination<G::Scalar>) -> LinearCombination<G::Scalar>,
LB: FnOnce(LinearCombination<G::Scalar>) -> LinearCombination<G::Scalar>,
LC: FnOnce(LinearCombination<G::Scalar>) -> LinearCombination<G::Scalar>,
LA: FnOnce(LinearCombination<<G as Group>::Scalar>) -> LinearCombination<<G as Group>::Scalar>,
LB: FnOnce(LinearCombination<<G as Group>::Scalar>) -> LinearCombination<<G as Group>::Scalar>,
LC: FnOnce(LinearCombination<<G as Group>::Scalar>) -> LinearCombination<<G as Group>::Scalar>,
{
let path = compute_path(&self.current_namespace, &annotation().into());
let index = self.constraints.len();
Expand Down
24 changes: 12 additions & 12 deletions src/bellperson/solver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ pub struct SatisfyingAssignment<G: Group> {
b_aux_density: DensityTracker,

// Evaluations of A, B, C polynomials
a: Vec<G::Scalar>,
b: Vec<G::Scalar>,
c: Vec<G::Scalar>,
a: Vec<<G as Group>::Scalar>,
b: Vec<<G as Group>::Scalar>,
c: Vec<<G as Group>::Scalar>,

// Assignments of variables
pub(crate) input_assignment: Vec<G::Scalar>,
pub(crate) aux_assignment: Vec<G::Scalar>,
pub(crate) input_assignment: Vec<<G as Group>::Scalar>,
pub(crate) aux_assignment: Vec<<G as Group>::Scalar>,
}
use std::fmt;

Expand Down Expand Up @@ -63,11 +63,11 @@ impl<G: Group> fmt::Debug for SatisfyingAssignment<G> {
}
}

impl<G: Group> ConstraintSystem<G::Scalar> for SatisfyingAssignment<G> {
impl<G: Group> ConstraintSystem<<G as Group>::Scalar> for SatisfyingAssignment<G> {
type Root = Self;

fn new() -> Self {
let input_assignment = vec![G::Scalar::ONE];
let input_assignment = vec![<G as Group>::Scalar::ONE];
let mut d = DensityTracker::new();
d.add_element();

Expand All @@ -85,7 +85,7 @@ impl<G: Group> ConstraintSystem<G::Scalar> for SatisfyingAssignment<G> {

fn alloc<F, A, AR>(&mut self, _: A, f: F) -> Result<Variable, SynthesisError>
where
F: FnOnce() -> Result<G::Scalar, SynthesisError>,
F: FnOnce() -> Result<<G as Group>::Scalar, SynthesisError>,
A: FnOnce() -> AR,
AR: Into<String>,
{
Expand All @@ -98,7 +98,7 @@ impl<G: Group> ConstraintSystem<G::Scalar> for SatisfyingAssignment<G> {

fn alloc_input<F, A, AR>(&mut self, _: A, f: F) -> Result<Variable, SynthesisError>
where
F: FnOnce() -> Result<G::Scalar, SynthesisError>,
F: FnOnce() -> Result<<G as Group>::Scalar, SynthesisError>,
A: FnOnce() -> AR,
AR: Into<String>,
{
Expand All @@ -112,9 +112,9 @@ impl<G: Group> ConstraintSystem<G::Scalar> for SatisfyingAssignment<G> {
where
A: FnOnce() -> AR,
AR: Into<String>,
LA: FnOnce(LinearCombination<G::Scalar>) -> LinearCombination<G::Scalar>,
LB: FnOnce(LinearCombination<G::Scalar>) -> LinearCombination<G::Scalar>,
LC: FnOnce(LinearCombination<G::Scalar>) -> LinearCombination<G::Scalar>,
LA: FnOnce(LinearCombination<<G as Group>::Scalar>) -> LinearCombination<<G as Group>::Scalar>,
LB: FnOnce(LinearCombination<<G as Group>::Scalar>) -> LinearCombination<<G as Group>::Scalar>,
LC: FnOnce(LinearCombination<<G as Group>::Scalar>) -> LinearCombination<<G as Group>::Scalar>,
{
// Do nothing: we don't care about linear-combination evaluations in this context.
}
Expand Down
4 changes: 2 additions & 2 deletions src/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl NovaAugmentedCircuitParams {
#[derive(Debug, Serialize, Deserialize)]
#[serde(bound = "")]
pub struct NovaAugmentedCircuitInputs<G: Group> {
params: G::Scalar, // Hash(Shape of u2, Gens for u2). Needed for computing the challenge.
params: <G as Group>::Scalar, // Hash(Shape of u2, Gens for u2). Needed for computing the challenge.
i: G::Base,
z0: Vec<G::Base>,
zi: Option<Vec<G::Base>>,
Expand All @@ -65,7 +65,7 @@ impl<G: Group> NovaAugmentedCircuitInputs<G> {
/// Create new inputs/witness for the verification circuit
#[allow(clippy::too_many_arguments)]
pub fn new(
params: G::Scalar,
params: <G as Group>::Scalar,
i: G::Base,
z0: Vec<G::Base>,
zi: Option<Vec<G::Base>>,
Expand Down
10 changes: 6 additions & 4 deletions src/gadgets/ecc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,7 @@ mod tests {
}
}

pub fn scalar_mul(&self, scalar: &G::Scalar) -> Self {
pub fn scalar_mul(&self, scalar: &<G as Group>::Scalar) -> Self {
let mut res = Self {
x: G::Base::ZERO,
y: G::Base::ZERO,
Expand Down Expand Up @@ -903,7 +903,7 @@ mod tests {

fn test_ecc_ops_with<C, G>()
where
C: CurveAffine<Base = G::Base, ScalarExt = G::Scalar>,
C: CurveAffine<Base = G::Base, ScalarExt = <G as Group>::Scalar>,
G: Group,
{
// perform some curve arithmetic
Expand Down Expand Up @@ -954,15 +954,17 @@ mod tests {
assert_eq!(e_curve, e_curve_2);
}

fn synthesize_smul<G, CS>(mut cs: CS) -> (AllocatedPoint<G>, AllocatedPoint<G>, G::Scalar)
fn synthesize_smul<G, CS>(
mut cs: CS,
) -> (AllocatedPoint<G>, AllocatedPoint<G>, <G as Group>::Scalar)
where
G: Group,
CS: ConstraintSystem<G::Base>,
{
let a = alloc_random_point(cs.namespace(|| "a")).unwrap();
inputize_allocted_point(&a, cs.namespace(|| "inputize a")).unwrap();

let s = G::Scalar::random(&mut OsRng);
let s = <G as Group>::Scalar::random(&mut OsRng);
// Allocate bits for s
let bits: Vec<AllocatedBit> = s
.to_le_bits()
Expand Down
16 changes: 12 additions & 4 deletions src/gadgets/r1cs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,22 @@ impl<G: Group> AllocatedRelaxedR1CSInstance<G> {
// Allocate X0 and X1. If the input instance is None, then allocate default values 0.
let X0 = BigNat::alloc_from_nat(
cs.namespace(|| "allocate X[0]"),
|| Ok(f_to_nat(&inst.map_or(G::Scalar::ZERO, |inst| inst.X[0]))),
|| {
Ok(f_to_nat(
&inst.map_or(<G as Group>::Scalar::ZERO, |inst| inst.X[0]),
))
},
limb_width,
n_limbs,
)?;

let X1 = BigNat::alloc_from_nat(
cs.namespace(|| "allocate X[1]"),
|| Ok(f_to_nat(&inst.map_or(G::Scalar::ZERO, |inst| inst.X[1]))),
|| {
Ok(f_to_nat(
&inst.map_or(<G as Group>::Scalar::ZERO, |inst| inst.X[1]),
))
},
limb_width,
n_limbs,
)?;
Expand All @@ -133,14 +141,14 @@ impl<G: Group> AllocatedRelaxedR1CSInstance<G> {

let X0 = BigNat::alloc_from_nat(
cs.namespace(|| "allocate x_default[0]"),
|| Ok(f_to_nat(&G::Scalar::ZERO)),
|| Ok(f_to_nat(&<G as Group>::Scalar::ZERO)),
limb_width,
n_limbs,
)?;

let X1 = BigNat::alloc_from_nat(
cs.namespace(|| "allocate x_default[1]"),
|| Ok(f_to_nat(&G::Scalar::ZERO)),
|| Ok(f_to_nat(&<G as Group>::Scalar::ZERO)),
limb_width,
n_limbs,
)?;
Expand Down
9 changes: 6 additions & 3 deletions src/gadgets/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,18 @@ pub fn alloc_one<F: PrimeField, CS: ConstraintSystem<F>>(
/// Allocate a scalar as a base. Only to be used is the scalar fits in base!
pub fn alloc_scalar_as_base<G, CS>(
mut cs: CS,
input: Option<G::Scalar>,
input: Option<<G as Group>::Scalar>,
) -> Result<AllocatedNum<G::Base>, SynthesisError>
where
G: Group,
<G as Group>::Scalar: PrimeFieldBits,
CS: ConstraintSystem<<G as Group>::Base>,
{
AllocatedNum::alloc(cs.namespace(|| "allocate scalar as base"), || {
let input_bits = input.unwrap_or(G::Scalar::ZERO).clone().to_le_bits();
let input_bits = input
.unwrap_or(<G as Group>::Scalar::ZERO)
.clone()
.to_le_bits();
let mut mult = G::Base::ONE;
let mut val = G::Base::ZERO;
for bit in input_bits {
Expand All @@ -99,7 +102,7 @@ where
}

/// interepret scalar as base
pub fn scalar_as_base<G: Group>(input: G::Scalar) -> G::Base {
pub fn scalar_as_base<G: Group>(input: <G as Group>::Scalar) -> G::Base {
let input_bits = input.to_le_bits();
let mut mult = G::Base::ONE;
let mut val = G::Base::ZERO;
Expand Down
Loading

0 comments on commit 5ee0590

Please sign in to comment.