mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-01-31 15:52:14 +00:00
Implementation of fixed-base Edwards scalar multiplication in the circuit.
This commit is contained in:
parent
69833e5162
commit
edc4adc32c
@ -17,7 +17,12 @@ use super::num::AllocatedNum;
|
||||
|
||||
use ::jubjub::{
|
||||
JubjubEngine,
|
||||
JubjubParams
|
||||
JubjubParams,
|
||||
FixedGenerators
|
||||
};
|
||||
|
||||
use super::lookup::{
|
||||
lookup3_xy
|
||||
};
|
||||
|
||||
use super::boolean::Boolean;
|
||||
@ -36,6 +41,56 @@ impl<E: Engine, Var: Copy> Clone for EdwardsPoint<E, Var> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform a fixed-base scalar multiplication with
|
||||
/// `by` being in little-endian bit order. `by` must
|
||||
/// be a multiple of 3.
|
||||
pub fn fixed_base_multiplication<E, Var, CS>(
|
||||
mut cs: CS,
|
||||
base: FixedGenerators,
|
||||
by: &[Boolean<Var>],
|
||||
params: &E::Params
|
||||
) -> Result<EdwardsPoint<E, Var>, SynthesisError>
|
||||
where CS: ConstraintSystem<E, Variable=Var>,
|
||||
E: JubjubEngine,
|
||||
Var: Copy
|
||||
{
|
||||
// We're going to chunk the scalar into 3-bit windows,
|
||||
// so let's force the caller to supply the right number
|
||||
// of bits for our lookups.
|
||||
assert!(by.len() % 3 == 0);
|
||||
|
||||
// Represents the result of the multiplication
|
||||
let mut result = None;
|
||||
|
||||
for (i, (chunk, window)) in by.chunks(3)
|
||||
.zip(params.circuit_generators(base).iter())
|
||||
.enumerate()
|
||||
{
|
||||
let (x, y) = lookup3_xy(
|
||||
cs.namespace(|| format!("window table lookup {}", i)),
|
||||
chunk,
|
||||
window
|
||||
)?;
|
||||
|
||||
let p = EdwardsPoint {
|
||||
x: x,
|
||||
y: y
|
||||
};
|
||||
|
||||
if result.is_none() {
|
||||
result = Some(p);
|
||||
} else {
|
||||
result = Some(result.unwrap().add(
|
||||
cs.namespace(|| format!("addition {}", i)),
|
||||
&p,
|
||||
params
|
||||
)?);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(result.get()?.clone())
|
||||
}
|
||||
|
||||
impl<E: JubjubEngine, Var: Copy> EdwardsPoint<E, Var> {
|
||||
/// This extracts the x-coordinate, which is an injective
|
||||
/// encoding for elements of the prime order subgroup.
|
||||
@ -615,13 +670,16 @@ mod test {
|
||||
use ::jubjub::{
|
||||
montgomery,
|
||||
edwards,
|
||||
JubjubBls12
|
||||
JubjubBls12,
|
||||
JubjubParams,
|
||||
FixedGenerators
|
||||
};
|
||||
use ::jubjub::fs::Fs;
|
||||
use super::{
|
||||
MontgomeryPoint,
|
||||
EdwardsPoint,
|
||||
AllocatedNum,
|
||||
fixed_base_multiplication
|
||||
};
|
||||
use super::super::boolean::{
|
||||
Boolean,
|
||||
@ -731,6 +789,41 @@ mod test {
|
||||
assert!(p.double(&mut cs, params).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_edwards_fixed_base_multiplication() {
|
||||
let params = &JubjubBls12::new();
|
||||
let rng = &mut XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
||||
for _ in 0..100 {
|
||||
let mut cs = TestConstraintSystem::<Bls12>::new();
|
||||
|
||||
let p = params.generator(FixedGenerators::NoteCommitmentRandomization);
|
||||
let s = Fs::rand(rng);
|
||||
let q = p.mul(s, params);
|
||||
let (x1, y1) = q.into_xy();
|
||||
|
||||
let mut s_bits = BitIterator::new(s.into_repr()).collect::<Vec<_>>();
|
||||
s_bits.reverse();
|
||||
s_bits.truncate(Fs::NUM_BITS as usize);
|
||||
|
||||
let s_bits = s_bits.into_iter()
|
||||
.enumerate()
|
||||
.map(|(i, b)| AllocatedBit::alloc(cs.namespace(|| format!("scalar bit {}", i)), Some(b)).unwrap())
|
||||
.map(|v| Boolean::from(v))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let q = fixed_base_multiplication(
|
||||
cs.namespace(|| "multiplication"),
|
||||
FixedGenerators::NoteCommitmentRandomization,
|
||||
&s_bits,
|
||||
params
|
||||
).unwrap();
|
||||
|
||||
assert_eq!(q.x.get_value().unwrap(), x1);
|
||||
assert_eq!(q.y.get_value().unwrap(), y1);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_edwards_multiplication() {
|
||||
let params = &JubjubBls12::new();
|
||||
|
@ -49,6 +49,8 @@ pub trait JubjubParams<E: JubjubEngine>: Sized {
|
||||
fn pedersen_circuit_generators(&self) -> &[Vec<Vec<(E::Fr, E::Fr)>>];
|
||||
|
||||
fn fixed_base_chunks_per_generator(&self) -> usize;
|
||||
fn generator(&self, base: FixedGenerators) -> &edwards::Point<E, PrimeOrder>;
|
||||
fn circuit_generators(&self, FixedGenerators) -> &[Vec<(E::Fr, E::Fr)>];
|
||||
}
|
||||
|
||||
pub enum Unknown { }
|
||||
@ -63,6 +65,7 @@ impl JubjubEngine for Bls12 {
|
||||
|
||||
/// Fixed generators of the Jubjub curve of unknown
|
||||
/// exponent.
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum FixedGenerators {
|
||||
NoteCommitmentRandomization = 0,
|
||||
Max = 1
|
||||
@ -98,6 +101,14 @@ impl JubjubParams<Bls12> for JubjubBls12 {
|
||||
fn pedersen_circuit_generators(&self) -> &[Vec<Vec<(Fr, Fr)>>] {
|
||||
&self.pedersen_circuit_generators
|
||||
}
|
||||
fn generator(&self, base: FixedGenerators) -> &edwards::Point<Bls12, PrimeOrder>
|
||||
{
|
||||
&self.fixed_base_generators[base as usize]
|
||||
}
|
||||
fn circuit_generators(&self, base: FixedGenerators) -> &[Vec<(Fr, Fr)>]
|
||||
{
|
||||
&self.fixed_base_circuit_generators[base as usize][..]
|
||||
}
|
||||
}
|
||||
|
||||
impl JubjubBls12 {
|
||||
|
Loading…
Reference in New Issue
Block a user