Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions keccak256/src/permutation/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,8 @@ impl<F: Field> KeccakFConfig<F> {
.try_into()
.unwrap();

let fixed = [
meta.fixed_column(),
meta.fixed_column(),
meta.fixed_column(),
];
let generic = GenericConfig::configure(meta, state[0..3].try_into().unwrap(), fixed[0]);
let fixed = meta.fixed_column();
let generic = GenericConfig::configure(meta, state[0..3].try_into().unwrap(), fixed);

// theta
let theta_config = ThetaConfig::configure(meta.selector(), meta, state);
Expand Down
15 changes: 6 additions & 9 deletions keccak256/src/permutation/rho.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl<F: Field> RhoConfig<F> {
pub fn configure(
meta: &mut ConstraintSystem<F>,
state: [Column<Advice>; 25],
fixed: [Column<Fixed>; 3],
fixed: Column<Fixed>,
generic: &GenericConfig<F>,
) -> Self {
state.iter().for_each(|col| meta.enable_equality(*col));
Expand All @@ -39,15 +39,16 @@ impl<F: Field> RhoConfig<F> {
meta,
&base13_to_9_table,
&special_chunk_table,
state[0..5].try_into().unwrap(),
state[0..3].try_into().unwrap(),
fixed,
generic.clone(),
);

let overflow_check_config = OverflowCheckConfig::configure(
meta,
&step2_range_table,
&step3_range_table,
state[5..7].try_into().unwrap(),
state[3],
generic.clone(),
);
Self {
Expand Down Expand Up @@ -155,13 +156,9 @@ mod tests {
.try_into()
.unwrap();

let fixed = [
meta.fixed_column(),
meta.fixed_column(),
meta.fixed_column(),
];
let fixed = meta.fixed_column();
let generic =
GenericConfig::configure(meta, state[0..3].try_into().unwrap(), fixed[0]);
GenericConfig::configure(meta, state[0..3].try_into().unwrap(), fixed);

let rho_config = RhoConfig::configure(meta, state, fixed, &generic);

Expand Down
230 changes: 76 additions & 154 deletions keccak256/src/permutation/rho_checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,74 +118,33 @@ use halo2_proofs::{
plonk::{Advice, Column, ConstraintSystem, Error, Fixed, Selector},
poly::Rotation,
};
use std::marker::PhantomData;

#[derive(Debug, Clone)]
pub struct LaneRotateConversionConfig<F> {
q_normal: Selector,
q_special: Selector,
input_coef: Column<Advice>,
input_pob: Column<Fixed>,
input_acc: Column<Advice>,
output_coef: Column<Advice>,
output_pob: Column<Fixed>,
output_acc: Column<Advice>,
pub overflow_detector: Column<Advice>,
_marker: PhantomData<F>,
generic: GenericConfig<F>,
Comment on lines -128 to +129
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is really really nice! Makes things a lot easier!

Will rebase this into the final keccak PR ASAP!

}

impl<F: Field> LaneRotateConversionConfig<F> {
pub fn configure(
meta: &mut ConstraintSystem<F>,
base13_to_9_table: &Base13toBase9TableConfig<F>,
special_chunk_table: &SpecialChunkTableConfig<F>,
advices: [Column<Advice>; 5],
fixed: [Column<Fixed>; 3],
advices: [Column<Advice>; 3],
constant: Column<Fixed>,
generic: GenericConfig<F>,
) -> Self {
let q_normal = meta.complex_selector();
let q_special = meta.complex_selector();
let [input_coef, input_acc, output_coef, output_acc, overflow_detector] = advices;
let [input_pob, output_pob, constant] = fixed;
let [input_coef, output_coef, overflow_detector] = advices;

meta.enable_equality(input_acc);
meta.enable_equality(output_acc);
meta.enable_equality(overflow_detector);
meta.enable_constant(constant);

// | coef | 13**x | acc |
// |------|-------|-----------|
// | a | b | c |
// | ... | ... | c - a * b |
meta.create_gate("Running down input", |meta| {
let q_normal = meta.query_selector(q_normal);
let coef = meta.query_advice(input_coef, Rotation::cur());
let pob = meta.query_fixed(input_pob, Rotation::cur());
let acc = meta.query_advice(input_acc, Rotation::cur());
let acc_next = meta.query_advice(input_acc, Rotation::next());
vec![(
"delta_acc === - coef * power_of_base",
q_normal * (acc_next - acc + coef * pob),
)]
});
// | coef | 9**x | acc |
// |------|-------|--------|
// | a | b | 0 |
// | ... | ... | a * b |
meta.create_gate("Running up for output", |meta| {
let q_normal = meta.query_selector(q_normal);
let q_special = meta.query_selector(q_special);
let coef = meta.query_advice(output_coef, Rotation::cur());
let pob = meta.query_fixed(output_pob, Rotation::cur());
let acc = meta.query_advice(output_acc, Rotation::cur());
let acc_next = meta.query_advice(output_acc, Rotation::next());
// delta_acc === coef * power_of_base
let poly = acc_next - acc - coef * pob;
vec![
("check for q_normal", q_normal * poly.clone()),
("check for q_special", q_special * poly),
]
});

meta.lookup("b13 -> b9 table", |meta| {
let q_normal = meta.query_selector(q_normal);
let base13_coef = meta.query_advice(input_coef, Rotation::cur());
Expand All @@ -201,12 +160,12 @@ impl<F: Field> LaneRotateConversionConfig<F> {

meta.lookup("special chunk", |meta| {
let q_special = meta.query_selector(q_special);
let input_acc = meta.query_advice(input_acc, Rotation::cur());
let input_coef = meta.query_advice(input_coef, Rotation::cur());
let output_coef = meta.query_advice(output_coef, Rotation::cur());

vec![
(
q_special.clone() * input_acc,
q_special.clone() * input_coef,
special_chunk_table.last_chunk,
),
(q_special * output_coef, special_chunk_table.output_coef),
Expand All @@ -216,13 +175,9 @@ impl<F: Field> LaneRotateConversionConfig<F> {
q_normal,
q_special,
input_coef,
input_pob,
input_acc,
output_coef,
output_pob,
output_acc,
overflow_detector,
_marker: PhantomData,
generic,
}
}

Expand All @@ -249,129 +204,97 @@ impl<F: Field> LaneRotateConversionConfig<F> {
rotation,
)
.get_full_witness();
layouter.assign_region(
|| "lane rotate conversion",
|mut region| {
let slices = slice_lane(rotation);
let (step2_od, step3_od) = {
let slices = slice_lane(rotation);

let (input_coefs, input_pobs, output_coefs, output_pobs, step2_od, step3_od) = layouter
.assign_region(
|| "lane rotate conversion",
|mut region| {
let mut input_coefs: Vec<AssignedCell<F, F>> = vec![];
let mut output_coefs: Vec<AssignedCell<F, F>> = vec![];
let mut input_pobs: Vec<F> = vec![];
let mut output_pobs: Vec<F> = vec![];
let mut step2_od: Vec<AssignedCell<F, F>> = vec![];
let mut step3_od: Vec<AssignedCell<F, F>> = vec![];
for (offset, (&(chunk_idx, step), conv)) in
slices.iter().zip(conversions.iter()).enumerate()
{
self.q_normal.enable(&mut region, offset)?;
region.assign_advice(
let input_coef = region.assign_advice(
|| format!("Input Coef {}", chunk_idx),
self.input_coef,
offset,
|| Ok(biguint_to_f::<F>(&conv.input.coef)),
)?;
region.assign_fixed(
|| "Input power of base",
self.input_pob,
offset,
|| Ok(biguint_to_f::<F>(&conv.input.power_of_base)),
)?;
{
let cell = region
.assign_advice(
|| "Input accumulator",
self.input_acc,
offset,
|| Ok(biguint_to_f::<F>(&conv.input.pre_acc)),
)?
.cell();
if offset == 0 {
region.constrain_equal(lane_base_13.cell(), cell)?;
}
}
region.assign_advice(
input_coefs.push(input_coef);
input_pobs.push(biguint_to_f::<F>(&conv.input.power_of_base));
let output_coef = region.assign_advice(
|| "Output Coef",
self.output_coef,
offset,
|| Ok(biguint_to_f::<F>(&conv.output.coef)),
)?;
region.assign_fixed(
|| "Output power of base",
self.output_pob,
output_coefs.push(output_coef);
output_pobs.push(biguint_to_f::<F>(&conv.output.power_of_base));

let od = region.assign_advice(
|| "Overflow detector",
self.overflow_detector,
offset,
|| Ok(biguint_to_f::<F>(&conv.output.power_of_base)),
|| Ok(F::from(conv.overflow_detector.value as u64)),
)?;
{
let cell = region
.assign_advice(
|| "Output accumulator",
self.output_acc,
offset,
|| Ok(biguint_to_f::<F>(&conv.output.pre_acc)),
)?
.cell();
if offset == 0 {
region.constrain_constant(cell, F::zero())?;
}
}
let od = {
let value = F::from(conv.overflow_detector.value as u64);
let od = region.assign_advice(
|| "Overflow detector",
self.overflow_detector,
offset,
|| Ok(value),
)?;
if step == 1 {
region.constrain_constant(od.cell(), F::zero())?;
}
od
};
match step {
1 => region.constrain_constant(od.cell(), F::zero())?,
2 => step2_od.push(od),
3 => step3_od.push(od),
_ => {}
4 => { // Do nothing
}
_ => unreachable!(),
}
}
(step2_od, step3_od)
};
// special chunks
let output_lane = {
let offset = slices.len();
self.q_special.enable(&mut region, offset)?;
region.assign_advice(
|| "Special Input acc",
self.input_acc,
offset,
|| Ok(biguint_to_f::<F>(&special.input)),
)?;
region.assign_advice(
|| "Special output coef",
self.output_coef,
offset,
|| Ok(F::from(special.output_coef as u64)),
)?;
region.assign_fixed(
|| "Special output power of base",
self.output_pob,
offset,
|| Ok(F::from(B9 as u64).pow(&[rotation.into(), 0, 0, 0])),
)?;
region.assign_advice(
|| "Special output acc pre",
self.output_acc,
offset,
|| Ok(biguint_to_f::<F>(&special.output_acc_pre)),
)?;
{
let value = biguint_to_f::<F>(&special.output_acc_post);
region.assign_advice(
|| "Special output acc post",
self.output_acc,
offset + 1,
|| Ok(value),
)?
}
};
Ok((output_lane, step2_od, step3_od))

Ok((
input_coefs,
input_pobs,
output_coefs,
output_pobs,
step2_od,
step3_od,
))
},
)?;
let input_from_chunks =
self.generic
.linear_combine_consts(layouter, input_coefs, input_pobs, None)?;
let diff = self
.generic
.sub_advice(layouter, lane_base_13, input_from_chunks)?;

let (final_output_coef, final_output_pob) = layouter.assign_region(
|| "special chunks",
|mut region| {
let offset = 0;
self.q_special.enable(&mut region, offset)?;
diff.copy_advice(|| "input lane diff", &mut region, self.input_coef, offset)?;
let output_coef = region.assign_advice(
|| "Special output coef",
self.output_coef,
offset,
|| Ok(F::from(special.output_coef as u64)),
)?;
let final_output_pob = F::from(B9 as u64).pow(&[rotation.into(), 0, 0, 0]);
Ok((output_coef, final_output_pob))
},
)
)?;
let mut output_coefs = output_coefs;
output_coefs.push(final_output_coef);
let mut output_pobs = output_pobs;
output_pobs.push(final_output_pob);

let output_lane =
self.generic
.linear_combine_consts(layouter, output_coefs, output_pobs, None)?;
Ok((output_lane, step2_od, step3_od))
}
}

Expand All @@ -387,12 +310,11 @@ impl<F: Field> OverflowCheckConfig<F> {
meta: &mut ConstraintSystem<F>,
step2_range_table: &RangeCheckConfig<F, STEP2_RANGE>,
step3_range_table: &RangeCheckConfig<F, STEP3_RANGE>,
advices: [Column<Advice>; 2],
acc: Column<Advice>,
generic: GenericConfig<F>,
) -> Self {
let q_step2 = meta.complex_selector();
let q_step3 = meta.complex_selector();
let acc = advices[0];
meta.enable_equality(acc);

meta.lookup("Overflow check step2", |meta| {
Expand Down