Skip to content

Commit

Permalink
feat: non-native ecc addition in sw form (#326)
Browse files Browse the repository at this point in the history
* benches

* remove redundant range checks

* optimize range checks

* changelog

* remove unnecessary comments

* refactor emulated ecc

* helper functions

* Point renamed to TEPoint. Refactored conversion.
Some edits to SW circuits

* SW Point struct

* rename symbols for readability

* ecc add for sw point

* cargo fmt

* CHANGELOG

* revert last merge

* revert previous merge

* add cargo.lock to avoid CI error

* comments and update dependency on crypto_kx

* Addressed comments;
add "create_public_boolean_variable"

* cargo fmt

* Serialization interfaces.
Add public inputs in test

* Updated documentation

* addressed comments
  • Loading branch information
mrain authored Jun 28, 2023
1 parent ce87395 commit 1b03cad
Show file tree
Hide file tree
Showing 20 changed files with 1,023 additions and 550 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ and follow [semantic versioning](https://semver.org/) for our releases.
- [#271](https://github.com/EspressoSystems/jellyfish/pull/271) Serde support for Aggregateable signatures
- [#291](https://github.com/EspressoSystems/jellyfish/pull/291) Non-native field operations and elliptic curve addition
- [#309](https://github.com/EspressoSystems/jellyfish/pull/309) Reed-Solomon decoder accept FFT domain
- [#320](https://github.com/EspressoSystems/jellyfish/pull/320) Non-native elliptic curve addition in short Weierstrass form

### Changed

Expand Down
6 changes: 3 additions & 3 deletions plonk/examples/proof_of_exp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use jf_plonk::{
proof_system::{PlonkKzgSnark, UniversalSNARK},
transcript::StandardTranscript,
};
use jf_relation::{gadgets::ecc::Point, Arithmetization, Circuit, PlonkCircuit};
use jf_relation::{gadgets::ecc::TEPoint, Arithmetization, Circuit, PlonkCircuit};
use jf_utils::fr_to_fq;
use rand_chacha::ChaCha20Rng;

Expand Down Expand Up @@ -124,11 +124,11 @@ where

// The next variable is a public constant: generator `G`.
// We need to convert the point to Jellyfish's own `Point` struct.
let G_jf: Point<EmbedCurve::BaseField> = G.into();
let G_jf: TEPoint<EmbedCurve::BaseField> = G.into();
let G_var = circuit.create_constant_point_variable(G_jf)?;

// The last variable is a public variable `X`.
let X_jf: Point<EmbedCurve::BaseField> = X.into();
let X_jf: TEPoint<EmbedCurve::BaseField> = X.into();
let X_var = circuit.create_public_point_variable(X_jf)?;

// Step 3:
Expand Down
32 changes: 16 additions & 16 deletions plonk/src/circuit/plonk_verifier/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use jf_primitives::rescue::RescueParameter;
use jf_relation::{
errors::{CircuitError, CircuitError::ParameterError},
gadgets::{
ecc::{MultiScalarMultiplicationCircuit, Point, PointVariable, SWToTEConParam},
ecc::{MultiScalarMultiplicationCircuit, PointVariable, SWToTEConParam, TEPoint},
ultraplonk::mod_arith::{FpElem, FpElemVar},
},
Circuit, PlonkCircuit, Variable,
Expand Down Expand Up @@ -65,12 +65,12 @@ impl<E: Pairing> VerifyingKeyVar<E> {
let sigma_comms = verify_key
.sigma_comms
.iter()
.map(|comm| circuit.create_point_variable(Point::from(&comm.0)))
.map(|comm| circuit.create_point_variable(TEPoint::from(comm.0)))
.collect::<Result<Vec<_>, CircuitError>>()?;
let selector_comms = verify_key
.selector_comms
.iter()
.map(|comm| circuit.create_point_variable(Point::from(&comm.0)))
.map(|comm| circuit.create_point_variable(TEPoint::from(comm.0)))
.collect::<Result<Vec<_>, CircuitError>>()?;
Ok(Self {
sigma_comms,
Expand Down Expand Up @@ -149,8 +149,8 @@ impl<E: Pairing> VerifyingKeyVar<E> {
/// The public inputs are already in the form of FpElemVars.
pub fn partial_verify_circuit<F, P>(
circuit: &mut PlonkCircuit<F>,
beta_g: &Point<F>,
generator_g: &Point<F>,
beta_g: &TEPoint<F>,
generator_g: &TEPoint<F>,
merged_vks: &[Self],
shared_public_input_vars: &[FpElemVar<F>],
batch_proof: &BatchProofVar<F>,
Expand Down Expand Up @@ -334,7 +334,7 @@ mod test {
use ark_std::{vec, UniformRand};
use jf_primitives::rescue::RescueParameter;
use jf_relation::{
gadgets::{ecc::Point, test_utils::test_variable_independence_for_circuit},
gadgets::{ecc::TEPoint, test_utils::test_variable_independence_for_circuit},
Circuit, MergeableCircuitType,
};
use jf_utils::{field_switching, test_rng};
Expand Down Expand Up @@ -445,11 +445,11 @@ mod test {
P: SWParam<BaseField = F>,
{
for (comm_var, comm) in vk_var.sigma_comms.iter().zip(vk.sigma_comms.iter()) {
let expected_comm = Point::from(&comm.0);
let expected_comm = TEPoint::from(comm.0);
assert_eq!(circuit.point_witness(comm_var).unwrap(), expected_comm);
}
for (comm_var, comm) in vk_var.selector_comms.iter().zip(vk.selector_comms.iter()) {
let expected_comm = Point::from(&comm.0);
let expected_comm = TEPoint::from(comm.0);
assert_eq!(circuit.point_witness(comm_var).unwrap(), expected_comm);
}
assert_eq!(vk_var.is_merged, vk.is_merged);
Expand Down Expand Up @@ -555,11 +555,11 @@ mod test {
);
assert_eq!(
circuit.point_witness(&partial_verify_points.0)?,
Point::<F>::from(&inner1.into_affine())
TEPoint::<F>::from(inner1.into_affine())
);
assert_eq!(
circuit.point_witness(&partial_verify_points.1)?,
Point::<F>::from(&inner2.into_affine())
TEPoint::<F>::from(inner2.into_affine())
);

// ark_std::println!("#variables: {}", circuit.num_vars());
Expand Down Expand Up @@ -650,11 +650,11 @@ mod test {
);
assert_ne!(
circuit.point_witness(&partial_verify_points.0)?,
Point::<F>::from(&inner1.into_affine())
TEPoint::<F>::from(inner1.into_affine())
);
assert_ne!(
circuit.point_witness(&partial_verify_points.1)?,
Point::<F>::from(&inner2.into_affine())
TEPoint::<F>::from(inner2.into_affine())
);

// wrong shared input and circuit input
Expand All @@ -673,11 +673,11 @@ mod test {
);
assert_ne!(
circuit.point_witness(&partial_verify_points.0)?,
Point::<F>::from(&inner1.into_affine())
TEPoint::<F>::from(inner1.into_affine())
);
assert_ne!(
circuit.point_witness(&partial_verify_points.1)?,
Point::<F>::from(&inner2.into_affine())
TEPoint::<F>::from(inner2.into_affine())
);
}
}
Expand Down Expand Up @@ -719,8 +719,8 @@ mod test {
// proof
let batch_proof_vars = (*batch_proof).create_variables(&mut circuit, m, two_power_m)?;

let beta_g: Point<F> = beta_g_ref.into();
let generator_g = &generator_g.into();
let beta_g: TEPoint<F> = (*beta_g_ref).into();
let generator_g = &(*generator_g).into();
let blinding_factor_var = circuit.create_variable(field_switching(blinding_factor))?;

let partial_verify_points = VerifyingKeyVar::partial_verify_circuit(
Expand Down
6 changes: 3 additions & 3 deletions plonk/src/circuit/transcript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ mod tests {
};
use ark_std::{format, UniformRand};
use jf_primitives::pcs::prelude::{Commitment, UnivariateVerifierParam};
use jf_relation::gadgets::ecc::Point;
use jf_relation::gadgets::ecc::TEPoint;
use jf_utils::{bytes_to_field_elements, field_switching, test_rng};

const RANGE_BIT_LEN_FOR_TEST: usize = 16;
Expand Down Expand Up @@ -349,7 +349,7 @@ mod tests {
let mut sigma_comms_vars: Vec<PointVariable> = Vec::new();
for e in sigma_comms.iter() {
// convert point into TE form
let p: Point<F> = (&e.0).into();
let p: TEPoint<F> = e.0.into();
sigma_comms_vars.push(circuit.create_point_variable(p).unwrap());
}

Expand All @@ -360,7 +360,7 @@ mod tests {
let mut selector_comms_vars: Vec<PointVariable> = Vec::new();
for e in selector_comms.iter() {
// convert point into TE form
let p: Point<F> = (&e.0).into();
let p: TEPoint<F> = e.0.into();
selector_comms_vars.push(circuit.create_point_variable(p).unwrap());
}

Expand Down
16 changes: 8 additions & 8 deletions plonk/src/proof_system/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use jf_primitives::{
use jf_relation::{
constants::{compute_coset_representatives, GATE_WIDTH, N_TURBO_PLONK_SELECTORS},
gadgets::{
ecc::{Point, SWToTEConParam},
ecc::{SWToTEConParam, TEPoint},
ultraplonk::mod_arith::FpElemVar,
},
PlonkCircuit,
Expand Down Expand Up @@ -358,14 +358,14 @@ impl<E: Pairing> BatchProof<E> {
for e in self.wires_poly_comms_vec.iter() {
let mut tmp = Vec::new();
for f in e.iter() {
let p: Point<F> = (&f.0).into();
let p: TEPoint<F> = f.0.into();
tmp.push(circuit.create_point_variable(p)?);
}
wires_poly_comms_vec.push(tmp);
}
let mut prod_perm_poly_comms_vec = Vec::new();
for e in self.prod_perm_poly_comms_vec.iter() {
let p: Point<F> = (&e.0).into();
let p: TEPoint<F> = e.0.into();
prod_perm_poly_comms_vec.push(circuit.create_point_variable(p)?);
}

Expand All @@ -377,14 +377,14 @@ impl<E: Pairing> BatchProof<E> {

let mut split_quot_poly_comms = Vec::new();
for e in self.split_quot_poly_comms.iter() {
let p: Point<F> = (&e.0).into();
let p: TEPoint<F> = e.0.into();
split_quot_poly_comms.push(circuit.create_point_variable(p)?);
}

let p: Point<F> = (&self.opening_proof.0).into();
let p: TEPoint<F> = self.opening_proof.0.into();
let opening_proof = circuit.create_point_variable(p)?;

let p: Point<F> = (&self.shifted_opening_proof.0).into();
let p: TEPoint<F> = self.shifted_opening_proof.0.into();
let shifted_opening_proof = circuit.create_point_variable(p)?;

Ok(BatchProofVar {
Expand Down Expand Up @@ -728,12 +728,12 @@ where
pub fn convert_te_coordinates_to_scalars(&self) -> Vec<F> {
let mut res = vec![];
for sigma_comm in self.sigma_comms.iter() {
let point: Point<F> = (&sigma_comm.0).into();
let point: TEPoint<F> = sigma_comm.0.into();
res.push(point.get_x());
res.push(point.get_y());
}
for selector_comm in self.selector_comms.iter() {
let point: Point<F> = (&selector_comm.0).into();
let point: TEPoint<F> = selector_comm.0.into();
res.push(point.get_x());
res.push(point.get_y());
}
Expand Down
8 changes: 4 additions & 4 deletions plonk/src/transcript/rescue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use jf_primitives::{
pcs::prelude::Commitment,
rescue::{RescueParameter, STATE_SIZE},
};
use jf_relation::gadgets::ecc::{Point, SWToTEConParam};
use jf_relation::gadgets::ecc::{SWToTEConParam, TEPoint};
use jf_utils::{bytes_to_field_elements, field_switching, fq_to_fr_with_mask};

/// Transcript with rescue hash function.
Expand Down Expand Up @@ -75,14 +75,14 @@ where
// selector commitments
for com in vk.selector_comms.iter() {
// convert the SW form commitments into TE form
let te_point: Point<F> = (&com.0).into();
let te_point: TEPoint<F> = com.0.into();
self.transcript.push(te_point.get_x());
self.transcript.push(te_point.get_y());
}
// sigma commitments
for com in vk.sigma_comms.iter() {
// convert the SW form commitments into TE form
let te_point: Point<F> = (&com.0).into();
let te_point: TEPoint<F> = com.0.into();
self.transcript.push(te_point.get_x());
self.transcript.push(te_point.get_y());
}
Expand Down Expand Up @@ -116,7 +116,7 @@ where
P: SWParam<BaseField = F>,
{
// convert the SW form commitments into TE form
let te_point: Point<F> = (&comm.0).into();
let te_point: TEPoint<F> = comm.0.into();
// push the x and y coordinate of comm (in twisted
// edwards form) to the transcript

Expand Down
12 changes: 6 additions & 6 deletions primitives/src/circuit/elgamal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use ark_ff::PrimeField;
use ark_std::{vec, vec::Vec};
use jf_relation::{
errors::CircuitError,
gadgets::ecc::{Point, PointVariable},
gadgets::ecc::{PointVariable, TEPoint},
Circuit, PlonkCircuit, Variable,
};
use jf_utils::compute_len_to_next_multiple;
Expand Down Expand Up @@ -224,7 +224,7 @@ where
}

fn create_enc_key_variable(&mut self, pk: &EncKey<P>) -> Result<EncKeyVars, CircuitError> {
let point = Point::from(pk.key.into_affine());
let point = TEPoint::from(pk.key.into_affine());
let point_variable = self.create_point_variable(point)?;
Ok(EncKeyVars(point_variable))
}
Expand All @@ -234,7 +234,7 @@ where
ctxts: &Ciphertext<P>,
) -> Result<ElGamalHybridCtxtVars, CircuitError> {
let ephemeral =
self.create_point_variable(Point::from(ctxts.ephemeral.key.into_affine()))?;
self.create_point_variable(TEPoint::from(ctxts.ephemeral.key.into_affine()))?;
let symm_ctxts = ctxts
.data
.iter()
Expand Down Expand Up @@ -264,7 +264,7 @@ mod tests {
use ark_ed_on_bn254::{EdwardsConfig as ParamEd254, Fq as FqEd254};
use ark_ff::UniformRand;
use ark_std::{vec, vec::Vec};
use jf_relation::{gadgets::ecc::Point, Circuit, PlonkCircuit, Variable};
use jf_relation::{gadgets::ecc::TEPoint, Circuit, PlonkCircuit, Variable};
use jf_utils::fr_to_fq;

#[test]
Expand Down Expand Up @@ -379,7 +379,7 @@ mod tests {

// Check ciphertexts
assert_eq!(
Point::from(ctxts.ephemeral.key.into_affine()),
TEPoint::from(ctxts.ephemeral.key.into_affine()),
circuit.point_witness(&ctxts_vars.ephemeral).unwrap()
);

Expand Down Expand Up @@ -433,7 +433,7 @@ mod tests {
let ctxts_var = circuit.create_ciphertext_variable(&ctxts).unwrap();
// Check ciphertexts
assert_eq!(
Point::from(ctxts.ephemeral.key.into_affine()),
TEPoint::from(ctxts.ephemeral.key.into_affine()),
circuit.point_witness(&ctxts_var.ephemeral).unwrap()
);
for (ctxt, ctxt_var) in ctxts.data.iter().zip(ctxts_var.symm_ctxts) {
Expand Down
6 changes: 3 additions & 3 deletions primitives/src/circuit/signature/schnorr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use ark_ff::PrimeField;
use ark_std::{vec, vec::Vec};
use jf_relation::{
errors::CircuitError,
gadgets::ecc::{Point, PointVariable},
gadgets::ecc::{PointVariable, TEPoint},
BoolVar, Circuit, PlonkCircuit, Variable,
};
use jf_utils::fr_to_fq;
Expand Down Expand Up @@ -123,13 +123,13 @@ where
) -> Result<SignatureVar, CircuitError> {
let sig_var = SignatureVar {
s: self.create_variable(fr_to_fq::<F, P>(&sig.s))?,
R: self.create_point_variable(Point::from(sig.R))?,
R: self.create_point_variable(TEPoint::from(sig.R))?,
};
Ok(sig_var)
}

fn create_signature_vk_variable(&mut self, vk: &VerKey<P>) -> Result<VerKeyVar, CircuitError> {
let vk_var = VerKeyVar(self.create_point_variable(Point::from(vk.0))?);
let vk_var = VerKeyVar(self.create_point_variable(TEPoint::from(vk.0))?);
Ok(vk_var)
}

Expand Down
8 changes: 8 additions & 0 deletions relation/src/constraint_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@ pub trait Circuit<F: Field> {
/// Add a public input variable; return the index of the variable.
fn create_public_variable(&mut self, val: F) -> Result<Variable, CircuitError>;

/// Add a public bool variable to the circuit; return the index of the
/// variable.
fn create_public_boolean_variable(&mut self, val: bool) -> Result<BoolVar, CircuitError> {
let val_scalar = if val { F::one() } else { F::zero() };
let var = self.create_public_variable(val_scalar)?;
Ok(BoolVar(var))
}

/// Set a variable to a public variable
fn set_variable_public(&mut self, var: Variable) -> Result<(), CircuitError>;

Expand Down
Loading

0 comments on commit 1b03cad

Please sign in to comment.