mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-01-31 15:52:14 +00:00
Implementation of 3-bit window table lookups.
This commit is contained in:
parent
9d49a60f48
commit
ba3ef9c84c
@ -124,6 +124,94 @@ pub fn pedersen_hash<E: JubjubEngine, CS, Var: Copy>(
|
||||
Ok(edwards_result.unwrap())
|
||||
}
|
||||
|
||||
/// Performs a 3-bit window table lookup. `bits` is in
|
||||
/// little-endian order.
|
||||
fn lookup3_xy<E: Engine, CS, Var: Copy>(
|
||||
mut cs: CS,
|
||||
bits: &[Boolean<Var>],
|
||||
coords: &[(E::Fr, E::Fr)]
|
||||
) -> Result<(AllocatedNum<E, Var>, AllocatedNum<E, Var>), SynthesisError>
|
||||
where CS: ConstraintSystem<E, Variable=Var>
|
||||
{
|
||||
assert_eq!(bits.len(), 3);
|
||||
assert_eq!(coords.len(), 8);
|
||||
|
||||
// Calculate the index into `coords`
|
||||
let i =
|
||||
match (bits[0].get_value(), bits[1].get_value(), bits[2].get_value()) {
|
||||
(Some(a_value), Some(b_value), Some(c_value)) => {
|
||||
let mut tmp = 0;
|
||||
if a_value {
|
||||
tmp += 1;
|
||||
}
|
||||
if b_value {
|
||||
tmp += 2;
|
||||
}
|
||||
if c_value {
|
||||
tmp += 4;
|
||||
}
|
||||
Some(tmp)
|
||||
},
|
||||
_ => None
|
||||
};
|
||||
|
||||
// Allocate the x-coordinate resulting from the lookup
|
||||
let res_x = AllocatedNum::alloc(
|
||||
cs.namespace(|| "x"),
|
||||
|| {
|
||||
Ok(coords[*i.get()?].0)
|
||||
}
|
||||
)?;
|
||||
|
||||
// Allocate the y-coordinate resulting from the lookup
|
||||
let res_y = AllocatedNum::alloc(
|
||||
cs.namespace(|| "y"),
|
||||
|| {
|
||||
Ok(coords[*i.get()?].1)
|
||||
}
|
||||
)?;
|
||||
|
||||
// Compute the coefficients for the lookup constraints
|
||||
let mut x_coeffs = [E::Fr::zero(); 8];
|
||||
let mut y_coeffs = [E::Fr::zero(); 8];
|
||||
synth::<E, _>(3, coords.iter().map(|c| &c.0), &mut x_coeffs);
|
||||
synth::<E, _>(3, coords.iter().map(|c| &c.1), &mut y_coeffs);
|
||||
|
||||
let precomp = Boolean::and(cs.namespace(|| "precomp"), &bits[1], &bits[2])?;
|
||||
|
||||
let one = cs.one();
|
||||
|
||||
cs.enforce(
|
||||
|| "x-coordinate lookup",
|
||||
LinearCombination::<Var, E>::zero() + (x_coeffs[0b001], one)
|
||||
+ &bits[1].lc::<E>(one, x_coeffs[0b011])
|
||||
+ &bits[2].lc::<E>(one, x_coeffs[0b101])
|
||||
+ &precomp.lc::<E>(one, x_coeffs[0b111]),
|
||||
LinearCombination::<Var, E>::zero() + &bits[0].lc::<E>(one, E::Fr::one()),
|
||||
LinearCombination::<Var, E>::zero() + res_x.get_variable()
|
||||
- (x_coeffs[0b000], one)
|
||||
- &bits[1].lc::<E>(one, x_coeffs[0b010])
|
||||
- &bits[2].lc::<E>(one, x_coeffs[0b100])
|
||||
- &precomp.lc::<E>(one, x_coeffs[0b110]),
|
||||
);
|
||||
|
||||
cs.enforce(
|
||||
|| "y-coordinate lookup",
|
||||
LinearCombination::<Var, E>::zero() + (y_coeffs[0b001], one)
|
||||
+ &bits[1].lc::<E>(one, y_coeffs[0b011])
|
||||
+ &bits[2].lc::<E>(one, y_coeffs[0b101])
|
||||
+ &precomp.lc::<E>(one, y_coeffs[0b111]),
|
||||
LinearCombination::<Var, E>::zero() + &bits[0].lc::<E>(one, E::Fr::one()),
|
||||
LinearCombination::<Var, E>::zero() + res_y.get_variable()
|
||||
- (y_coeffs[0b000], one)
|
||||
- &bits[1].lc::<E>(one, y_coeffs[0b010])
|
||||
- &bits[2].lc::<E>(one, y_coeffs[0b100])
|
||||
- &precomp.lc::<E>(one, y_coeffs[0b110]),
|
||||
);
|
||||
|
||||
Ok((res_x, res_y))
|
||||
}
|
||||
|
||||
/// Performs a 3-bit window table lookup, where
|
||||
/// one of the bits is a sign bit.
|
||||
fn lookup3_xy_with_conditional_negation<E: Engine, CS, Var: Copy>(
|
||||
@ -270,6 +358,46 @@ mod test {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lookup3_xy() {
|
||||
let mut rng = XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0656]);
|
||||
|
||||
for _ in 0..100 {
|
||||
let mut cs = TestConstraintSystem::<Bls12>::new();
|
||||
|
||||
let a_val = rng.gen();
|
||||
let a = Boolean::from(
|
||||
AllocatedBit::alloc(cs.namespace(|| "a"), Some(a_val)).unwrap()
|
||||
);
|
||||
|
||||
let b_val = rng.gen();
|
||||
let b = Boolean::from(
|
||||
AllocatedBit::alloc(cs.namespace(|| "b"), Some(b_val)).unwrap()
|
||||
);
|
||||
|
||||
let c_val = rng.gen();
|
||||
let c = Boolean::from(
|
||||
AllocatedBit::alloc(cs.namespace(|| "c"), Some(c_val)).unwrap()
|
||||
);
|
||||
|
||||
let bits = vec![a, b, c];
|
||||
|
||||
let points: Vec<(Fr, Fr)> = (0..8).map(|_| (rng.gen(), rng.gen())).collect();
|
||||
|
||||
let res = lookup3_xy(&mut cs, &bits, &points).unwrap();
|
||||
|
||||
assert!(cs.is_satisfied());
|
||||
|
||||
let mut index = 0;
|
||||
if a_val { index += 1 }
|
||||
if b_val { index += 2 }
|
||||
if c_val { index += 4 }
|
||||
|
||||
assert_eq!(res.0.get_value().unwrap(), points[index].0);
|
||||
assert_eq!(res.1.get_value().unwrap(), points[index].1);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lookup3_xy_with_conditional_negation() {
|
||||
let mut rng = XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||
|
Loading…
Reference in New Issue
Block a user