Skip to content

Commit

Permalink
Remove biguint to field (privacy-scaling-explorations#283)
Browse files Browse the repository at this point in the history
* remove biguint to field

* comment on the assumption
  • Loading branch information
ChihChengLiang authored Jan 15, 2022
1 parent 0230b6a commit 603409a
Show file tree
Hide file tree
Showing 13 changed files with 53 additions and 63 deletions.
16 changes: 0 additions & 16 deletions keccak256/src/arith_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use itertools::Itertools;
use num_bigint::BigUint;
use num_traits::Zero;
use pairing::arithmetic::FieldExt;
use pairing::bn256::Fr as Fp;
use std::ops::{Index, IndexMut};

pub const B2: u8 = 2;
Expand Down Expand Up @@ -188,21 +187,6 @@ pub fn convert_b9_lane_to_b2_normal(x: Lane9) -> u64 {
.unwrap_or(0)
}

pub fn big_uint_to_field<F: FieldExt>(a: &BigUint) -> F {
let mut b: [u64; 4] = [0; 4];
let mut iter = a.iter_u64_digits();

for i in &mut b {
*i = match &iter.next() {
Some(x) => *x,
None => 0u64,
};
}

// Workarround since `FieldExt` does not impl `from_raw`.
F::from_bytes(&Fp::from_raw(b).to_bytes()).unwrap()
}

/// This function allows us to inpect coefficients of big-numbers in different
/// bases.
pub fn inspect(x: BigUint, name: &str, base: u8) {
Expand Down
6 changes: 3 additions & 3 deletions keccak256/src/gates/absorb.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::arith_helpers::*;
use crate::common::*;
use crate::gates::gate_helpers::biguint_to_f;
use crate::keccak_arith::*;
use halo2::circuit::Cell;
use halo2::circuit::Layouter;
Expand Down Expand Up @@ -177,9 +178,8 @@ impl<F: FieldExt> AbsorbConfig<F> {
state[(x, y)].clone().try_into().expect("Conversion err"),
);
next_biguint[(x, y)] = convert_b2_to_b9(next_input[x][y]);
in_state[5 * x + y] = big_uint_to_field(&in_biguint[(x, y)]);
in_next_input_25[5 * x + y] =
big_uint_to_field(&next_biguint[(x, y)]);
in_state[5 * x + y] = biguint_to_f(&in_biguint[(x, y)]);
in_next_input_25[5 * x + y] = biguint_to_f(&next_biguint[(x, y)]);
}

let mut in_next_input_17 = [Fp::zero(); ABSORB_NEXT_INPUTS];
Expand Down
3 changes: 1 addition & 2 deletions keccak256/src/gates/base_conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,7 @@ mod tests {
let input = 12345678u64;
let circuit = MyCircuit::<Fp> {
input_b2_lane: Fp::from(input),
output_b13_lane: biguint_to_f::<Fp>(&convert_b2_to_b13(input))
.unwrap(),
output_b13_lane: biguint_to_f::<Fp>(&convert_b2_to_b13(input)),
};
let k = 17;

Expand Down
33 changes: 17 additions & 16 deletions keccak256/src/gates/gate_helpers.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
use halo2::{circuit::Cell, plonk::Error};
use halo2::circuit::Cell;
use num_bigint::BigUint;
use pairing::arithmetic::FieldExt;

#[derive(Debug, Clone)]
pub struct Lane<F> {
pub cell: Cell,
pub value: F,
}
use std::convert::TryInto;

#[derive(Debug, Clone, Copy)]
pub struct BlockCount<F> {
Expand All @@ -16,17 +11,23 @@ pub struct BlockCount<F> {

pub type BlockCount2<F> = (BlockCount<F>, BlockCount<F>);

pub fn biguint_to_f<F: FieldExt>(x: &BigUint) -> Result<F, Error> {
let mut word = [0; 32];
let x_bytes = x.to_bytes_le();
let len = x_bytes.len();
assert!(len <= 32, "expect len <=32 but got {}", len);
word[..len].clone_from_slice(&x_bytes[..len]);
Option::from(F::from_bytes(&word)).ok_or(Error::Synthesis)
/// Convert a bigUint value to FieldExt
///
/// We assume the input value is smaller than the field size
pub fn biguint_to_f<F: FieldExt>(x: &BigUint) -> F {
let mut x_bytes = x.to_bytes_le();
assert!(
x_bytes.len() <= 32,
"expect len <=32 but got {}",
x_bytes.len()
);
x_bytes.resize(32, 0);
let x_bytes: [u8; 32] = x_bytes.try_into().unwrap();
F::from_bytes(&x_bytes).unwrap()
}

pub fn f_to_biguint<F: FieldExt>(x: F) -> Option<BigUint> {
Option::from(BigUint::from_bytes_le(&x.to_bytes()[..]))
pub fn f_to_biguint<F: FieldExt>(x: F) -> BigUint {
BigUint::from_bytes_le(&x.to_bytes())
}

pub fn biguint_mod(x: &BigUint, modulus: u8) -> u8 {
Expand Down
3 changes: 2 additions & 1 deletion keccak256/src/gates/iota_b13.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ impl<F: FieldExt> IotaB13Config<F> {
mod tests {
use super::*;
use crate::common::{PERMUTATION, ROUND_CONSTANTS};
use crate::gates::gate_helpers::biguint_to_f;
use halo2::circuit::Layouter;
use halo2::plonk::{Advice, Column, ConstraintSystem, Error};
use halo2::{circuit::SimpleFloorPlanner, dev::MockProver, plonk::Circuit};
Expand Down Expand Up @@ -321,7 +322,7 @@ mod tests {

let constants: Vec<Fp> = ROUND_CONSTANTS
.iter()
.map(|num| big_uint_to_field(&convert_b2_to_b13(*num)))
.map(|num| biguint_to_f(&convert_b2_to_b13(*num)))
.collect();

// With flag set to true, the gate should trigger as we Mix.
Expand Down
10 changes: 6 additions & 4 deletions keccak256/src/gates/iota_b9.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::arith_helpers::*;
use crate::common::*;
use crate::gates::gate_helpers::biguint_to_f;
use crate::keccak_arith::*;
use halo2::circuit::Cell;
use halo2::circuit::Layouter;
Expand Down Expand Up @@ -265,7 +266,7 @@ impl<F: FieldExt> IotaB9Config<F> {
in_biguint[(x, y)] = convert_b2_to_b9(
state[(x, y)].clone().try_into().expect("Conversion err"),
);
in_state[5 * x + y] = big_uint_to_field(&in_biguint[(x, y)]);
in_state[5 * x + y] = biguint_to_f(&in_biguint[(x, y)]);
}

// Compute out state
Expand All @@ -279,6 +280,7 @@ impl<F: FieldExt> IotaB9Config<F> {
mod tests {
use super::*;
use crate::common::{PERMUTATION, ROUND_CONSTANTS};
use crate::gates::gate_helpers::biguint_to_f;
use halo2::circuit::Layouter;
use halo2::plonk::{Advice, Column, ConstraintSystem, Error};
use halo2::{circuit::SimpleFloorPlanner, dev::MockProver, plonk::Circuit};
Expand Down Expand Up @@ -399,7 +401,7 @@ mod tests {

let constants: Vec<Fp> = ROUND_CONSTANTS
.iter()
.map(|num| big_uint_to_field(&convert_b2_to_b9(*num)))
.map(|num| biguint_to_f(&convert_b2_to_b9(*num)))
.collect();

// (flag = 0) -> Out state is checked as constraints are applied.
Expand Down Expand Up @@ -551,7 +553,7 @@ mod tests {

for (x, y) in (0..5).cartesian_product(0..5) {
in_biguint[(x, y)] = convert_b2_to_b9(input1[x][y]);
in_state[5 * x + y] = big_uint_to_field(&in_biguint[(x, y)]);
in_state[5 * x + y] = biguint_to_f(&in_biguint[(x, y)]);
}

// Test for the 25 rounds
Expand All @@ -571,7 +573,7 @@ mod tests {

let constants: Vec<Fp> = ROUND_CONSTANTS
.iter()
.map(|num| big_uint_to_field(&convert_b2_to_b9(*num)))
.map(|num| biguint_to_f(&convert_b2_to_b9(*num)))
.collect();

let prover =
Expand Down
5 changes: 3 additions & 2 deletions keccak256/src/gates/mixing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ impl<F: FieldExt> MixingConfig<F> {
mod tests {
use super::*;
use crate::common::{State, PERMUTATION, ROUND_CONSTANTS};
use crate::gates::gate_helpers::biguint_to_f;
use halo2::circuit::Layouter;
use halo2::plonk::{ConstraintSystem, Error};
use halo2::{circuit::SimpleFloorPlanner, dev::MockProver, plonk::Circuit};
Expand Down Expand Up @@ -325,12 +326,12 @@ mod tests {

let constants_b13: Vec<Fp> = ROUND_CONSTANTS
.iter()
.map(|num| big_uint_to_field(&convert_b2_to_b13(*num)))
.map(|num| biguint_to_f(&convert_b2_to_b13(*num)))
.collect();

let constants_b9: Vec<Fp> = ROUND_CONSTANTS
.iter()
.map(|num| big_uint_to_field(&convert_b2_to_b9(*num)))
.map(|num| biguint_to_f(&convert_b2_to_b9(*num)))
.collect();

// With flag set to false, we don't mix. And so we should obtain Absorb
Expand Down
4 changes: 2 additions & 2 deletions keccak256/src/gates/rho.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,12 +233,12 @@ mod tests {
}
let s0_arith = KeccakFArith::theta(&in_biguint);
for (x, y) in (0..5).cartesian_product(0..5) {
in_state[5 * x + y] = biguint_to_f(&s0_arith[(x, y)]).unwrap();
in_state[5 * x + y] = biguint_to_f(&s0_arith[(x, y)]);
}
let s1_arith = KeccakFArith::rho(&s0_arith);
let mut out_state: [Fp; 25] = [Fp::zero(); 25];
for (x, y) in (0..5).cartesian_product(0..5) {
out_state[5 * x + y] = biguint_to_f(&s1_arith[(x, y)]).unwrap();
out_state[5 * x + y] = biguint_to_f(&s1_arith[(x, y)]);
}
let circuit = MyCircuit::<Fp> {
in_state,
Expand Down
22 changes: 11 additions & 11 deletions keccak256/src/gates/rho_checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ impl<F: FieldExt> LaneRotateConversionConfig<F> {
region.constrain_equal(lane_base_13.0, cell)?;

let mut rv = RotatingVariables::from(
f_to_biguint(lane_base_13.1).ok_or(Error::Synthesis)?,
f_to_biguint(lane_base_13.1),
self.rotation,
)?;
let all_block_counts: Result<Vec<BlockCount2<F>>, Error> = self
Expand Down Expand Up @@ -507,11 +507,11 @@ impl<F: FieldExt> ChunkRotateConversionConfig<F> {
rv: &RotatingVariables,
) -> Result<BlockCount2<F>, Error> {
assert_eq!(
biguint_to_f::<F>(&rv.input_power_of_base)?,
biguint_to_f::<F>(&rv.input_power_of_base),
self.power_of_b13
);
assert_eq!(
biguint_to_f::<F>(&rv.output_power_of_base)?,
biguint_to_f::<F>(&rv.output_power_of_base),
self.power_of_b9
);
self.q_enable.enable(region, offset)?;
Expand All @@ -522,25 +522,25 @@ impl<F: FieldExt> ChunkRotateConversionConfig<F> {
|| format!("Input Coef {}", self.chunk_idx),
self.adv.input.coef,
offset,
|| biguint_to_f::<F>(&rv.input_coef),
|| Ok(biguint_to_f::<F>(&rv.input_coef)),
)?;
region.assign_advice(
|| "Input accumulator",
self.adv.input.acc,
offset,
|| biguint_to_f::<F>(&rv.input_acc),
|| Ok(biguint_to_f::<F>(&rv.input_acc)),
)?;
region.assign_advice(
|| "Output Coef",
self.adv.output.coef,
offset,
|| biguint_to_f::<F>(&rv.output_coef),
|| Ok(biguint_to_f::<F>(&rv.output_coef)),
)?;
region.assign_advice(
|| "Output accumulator",
self.adv.output.acc,
offset,
|| biguint_to_f::<F>(&rv.output_acc),
|| Ok(biguint_to_f::<F>(&rv.output_acc)),
)?;
let block_counts = self.block_count_acc_config.assign_region(
region,
Expand Down Expand Up @@ -612,19 +612,19 @@ impl<F: FieldExt> SpecialChunkConfig<F> {
|| "input_acc",
self.base_13_acc,
offset,
|| biguint_to_f::<F>(&rv.input_acc),
|| Ok(biguint_to_f::<F>(&rv.input_acc)),
)?;
region.assign_advice(
|| "ouput_acc",
self.base_9_acc,
offset,
|| biguint_to_f::<F>(&rv.output_acc),
|| Ok(biguint_to_f::<F>(&rv.output_acc)),
)?;
region.assign_advice(
|| "last_b9_coef",
self.last_b9_coef,
offset,
|| biguint_to_f::<F>(&rv.output_coef),
|| Ok(biguint_to_f::<F>(&rv.output_coef)),
)?;

let rv_final = rv.finalize();
Expand All @@ -634,7 +634,7 @@ impl<F: FieldExt> SpecialChunkConfig<F> {
offset + 1,
|| Ok(F::zero()),
)?;
let value = biguint_to_f::<F>(&rv_final.output_acc)?;
let value = biguint_to_f::<F>(&rv_final.output_acc);
let cell = region.assign_advice(
|| "input_acc",
self.base_9_acc,
Expand Down
2 changes: 1 addition & 1 deletion keccak256/src/gates/state_conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ mod tests {
.unwrap();
let out_state: [Fp; 25] = in_state_flat
.iter()
.map(|&x| biguint_to_f::<Fp>(&convert_b2_to_b13(*x)).unwrap())
.map(|&x| biguint_to_f::<Fp>(&convert_b2_to_b13(*x)))
.collect::<Vec<_>>()
.try_into()
.unwrap();
Expand Down
2 changes: 1 addition & 1 deletion keccak256/src/gates/tables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ impl<F: FieldExt> BaseInfo<F> {
) -> Result<(Vec<F>, Vec<F>, F), Error> {
// big-endian
let input_chunks: Vec<u8> = {
let raw = f_to_biguint(input).ok_or(Error::Synthesis)?;
let raw = f_to_biguint(input);
let mut v = raw.to_radix_le(self.input_base.into());
assert!(v.len() <= self.max_chunks);
// fill 0 to max chunks
Expand Down
5 changes: 3 additions & 2 deletions keccak256/src/gates/theta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ impl<F: FieldExt> ThetaConfig<F> {
mod tests {
use super::*;
use crate::common::*;
use crate::gates::gate_helpers::biguint_to_f;
use crate::keccak_arith::*;
use halo2::{
circuit::{Layouter, SimpleFloorPlanner},
Expand Down Expand Up @@ -202,12 +203,12 @@ mod tests {

for (x, y) in (0..5).cartesian_product(0..5) {
in_biguint[(x, y)] = convert_b2_to_b13(input1[x][y]);
in_state[5 * x + y] = big_uint_to_field(&in_biguint[(x, y)]);
in_state[5 * x + y] = biguint_to_f(&in_biguint[(x, y)]);
}
let s1_arith = KeccakFArith::theta(&in_biguint);
let mut out_state: [Fp; 25] = [Fp::zero(); 25];
for (x, y) in (0..5).cartesian_product(0..5) {
out_state[5 * x + y] = big_uint_to_field(&s1_arith[(x, y)]);
out_state[5 * x + y] = biguint_to_f(&s1_arith[(x, y)]);
}

let circuit = MyCircuit::<Fp> {
Expand Down
5 changes: 3 additions & 2 deletions keccak256/src/gates/xi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ mod tests {
use super::*;
use crate::arith_helpers::*;
use crate::common::*;
use crate::gates::gate_helpers::biguint_to_f;
use crate::keccak_arith::*;
use halo2::circuit::Layouter;
use halo2::plonk::{Advice, Column, ConstraintSystem, Error};
Expand Down Expand Up @@ -208,12 +209,12 @@ mod tests {

for (x, y) in (0..5).cartesian_product(0..5) {
in_biguint[(x, y)] = convert_b2_to_b9(input1[x][y]);
in_state[5 * x + y] = big_uint_to_field(&in_biguint[(x, y)]);
in_state[5 * x + y] = biguint_to_f(&in_biguint[(x, y)]);
}
let s1_arith = KeccakFArith::xi(&in_biguint);
let mut out_state: [Fp; 25] = [Fp::zero(); 25];
for (x, y) in (0..5).cartesian_product(0..5) {
out_state[5 * x + y] = big_uint_to_field(&s1_arith[(x, y)]);
out_state[5 * x + y] = biguint_to_f(&s1_arith[(x, y)]);
}
let circuit = MyCircuit::<Fp> {
in_state,
Expand Down

0 comments on commit 603409a

Please sign in to comment.