Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.

Commit 7e32f91

Browse files
replace iota with generic
1 parent a90e59d commit 7e32f91

File tree

3 files changed

+43
-201
lines changed

3 files changed

+43
-201
lines changed

keccak256/src/permutation/circuit.rs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::{
33
common::{NEXT_INPUTS_LANES, PERMUTATION, ROUND_CONSTANTS},
44
keccak_arith::*,
55
permutation::{
6-
base_conversion::BaseConversionConfig, generic::GenericConfig, iota::IotaConfig,
6+
base_conversion::BaseConversionConfig, generic::GenericConfig, iota::IotaConstants,
77
mixing::MixingConfig, pi::pi_gate_permutation, rho::RhoConfig,
88
tables::FromBase9TableConfig, theta::ThetaConfig, xi::XiConfig,
99
},
@@ -16,13 +16,12 @@ use halo2_proofs::{
1616
};
1717
use itertools::Itertools;
1818
use std::convert::TryInto;
19-
2019
#[derive(Clone, Debug)]
2120
pub struct KeccakFConfig<F: Field> {
21+
generic: GenericConfig<F>,
2222
theta_config: ThetaConfig<F>,
2323
rho_config: RhoConfig<F>,
2424
xi_config: XiConfig<F>,
25-
iota_config: IotaConfig<F>,
2625
from_b9_table: FromBase9TableConfig<F>,
2726
base_conversion_config: BaseConversionConfig<F>,
2827
mixing_config: MixingConfig<F>,
@@ -44,7 +43,6 @@ impl<F: Field> KeccakFConfig<F> {
4443
.try_into()
4544
.unwrap();
4645

47-
let flag = meta.advice_column();
4846
let fixed = [
4947
meta.fixed_column(),
5048
meta.fixed_column(),
@@ -58,7 +56,6 @@ impl<F: Field> KeccakFConfig<F> {
5856
let rho_config = RhoConfig::configure(meta, state, fixed, &generic);
5957
// xi
6058
let xi_config = XiConfig::configure(meta.selector(), meta, state);
61-
let iota_config = IotaConfig::configure(meta, state[0], flag, fixed[0]);
6259

6360
// Allocate space for the activation flag of the base_conversion.
6461
let base_conv_activator = meta.advice_column();
@@ -77,8 +74,7 @@ impl<F: Field> KeccakFConfig<F> {
7774

7875
// Mixing will make sure that the flag is binary constrained and that
7976
// the out state matches the expected result.
80-
let mixing_config =
81-
MixingConfig::configure(meta, &from_b9_table, iota_config.clone(), state);
77+
let mixing_config = MixingConfig::configure(meta, &from_b9_table, state, generic.clone());
8278

8379
// Allocate the `out state correctness` gate selector
8480
let q_out = meta.selector();
@@ -97,10 +93,10 @@ impl<F: Field> KeccakFConfig<F> {
9793
});
9894

9995
KeccakFConfig {
96+
generic,
10097
theta_config,
10198
rho_config,
10299
xi_config,
103-
iota_config,
104100
from_b9_table,
105101
base_conversion_config,
106102
mixing_config,
@@ -162,9 +158,12 @@ impl<F: Field> KeccakFConfig<F> {
162158
}
163159

164160
// iota_b9
165-
state[0] = self
166-
.iota_config
167-
.assign_round_b9(layouter, state[0].clone(), round_idx)?;
161+
let iota_constants = IotaConstants::default();
162+
state[0] = self.generic.add_fixed(
163+
layouter,
164+
state[0].clone(),
165+
iota_constants.a4_times_round_constants_b9[round_idx],
166+
)?;
168167

169168
// The resulting state is in Base-9 now. We now convert it to
170169
// base_13 which is what Theta requires again at the

keccak256/src/permutation/iota.rs

Lines changed: 5 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -2,62 +2,17 @@ use crate::arith_helpers::{convert_b2_to_b13, convert_b2_to_b9, A4};
22
use crate::common::{PERMUTATION, ROUND_CONSTANTS};
33
use crate::gate_helpers::biguint_to_f;
44
use eth_types::Field;
5-
use halo2_proofs::circuit::AssignedCell;
6-
use halo2_proofs::circuit::Layouter;
7-
use halo2_proofs::{
8-
plonk::{Advice, Column, ConstraintSystem, Error, Fixed, Selector},
9-
poly::Rotation,
10-
};
115
use itertools::Itertools;
126
use std::convert::TryInto;
137

148
#[derive(Clone, Debug)]
15-
pub struct IotaConfig<F> {
16-
q_enable: Selector,
17-
lane00: Column<Advice>,
18-
flag: Column<Advice>,
19-
round_constant: Column<Fixed>,
20-
round_constant_b13: F,
21-
a4_times_round_constants_b9: [F; PERMUTATION],
9+
pub struct IotaConstants<F> {
10+
pub round_constant_b13: F,
11+
pub a4_times_round_constants_b9: [F; PERMUTATION],
2212
}
2313

24-
impl<F: Field> IotaConfig<F> {
25-
/// Iota step adds a round constant to the first lane.
26-
///
27-
/// We enable the gate to handle 3 different cases:
28-
///
29-
/// The first case takes place in the first 23 rounds, the prover MUST add
30-
/// the `A4` times round constant in base 9. We enforce it by requiring the
31-
/// flag equal to one.
32-
///
33-
/// The second the third cases happen in the 24-th
34-
/// round. It depends if prover wants to absorb new input or not, which is
35-
/// indicated by the flag.
36-
///
37-
/// If prover doesn't want to absorb new input,
38-
/// then add `A4 * round_constant_b9` as the previous 23-th round did.
39-
///
40-
/// Otherwise, apply the round constant in base 13 to the state, which has
41-
/// been mixed with new input and converted form base 9 to base 13.
42-
pub fn configure(
43-
meta: &mut ConstraintSystem<F>,
44-
lane00: Column<Advice>,
45-
flag: Column<Advice>,
46-
round_constant: Column<Fixed>,
47-
) -> Self {
48-
let q_enable = meta.selector();
49-
meta.enable_equality(lane00);
50-
meta.enable_equality(flag);
51-
52-
meta.create_gate("iota", |meta| {
53-
let q_enable = meta.query_selector(q_enable);
54-
let flag = meta.query_advice(flag, Rotation::cur());
55-
let lane00_next = meta.query_advice(lane00, Rotation::next());
56-
let lane00 = meta.query_advice(lane00, Rotation::cur());
57-
let round_constant = meta.query_fixed(round_constant, Rotation::cur());
58-
vec![q_enable * (lane00_next - lane00 - flag * round_constant)]
59-
});
60-
14+
impl<F: Field> Default for IotaConstants<F> {
15+
fn default() -> Self {
6116
let round_constant_b13 =
6217
biguint_to_f::<F>(&convert_b2_to_b13(ROUND_CONSTANTS[PERMUTATION - 1]));
6318

@@ -72,132 +27,8 @@ impl<F: Field> IotaConfig<F> {
7227
.unwrap();
7328

7429
Self {
75-
q_enable,
76-
lane00,
77-
flag,
78-
round_constant,
7930
round_constant_b13,
8031
a4_times_round_constants_b9,
8132
}
8233
}
83-
84-
/// The first 23 rounds. (No mixing logic involved).
85-
///
86-
/// Applies IotaB9 steady-step logic.
87-
/// It consists of: `new_lane_00 - (lane00 * ROUND_CTANTS[round]) == 0`.
88-
pub fn assign_round_b9(
89-
&self,
90-
layouter: &mut impl Layouter<F>,
91-
lane00: AssignedCell<F, F>,
92-
round: usize,
93-
) -> Result<AssignedCell<F, F>, Error> {
94-
layouter.assign_region(
95-
|| "IotaB9",
96-
|mut region| {
97-
let offset = 0;
98-
self.q_enable.enable(&mut region, offset)?;
99-
lane00.copy_advice(|| "lane 00", &mut region, self.lane00, offset)?;
100-
// In the normal round, we must add round constant. constrain flag to 1.
101-
let flag = region.assign_advice(|| "flag", self.flag, offset, || Ok(F::one()))?;
102-
region.constrain_constant(flag.cell(), F::one())?;
103-
104-
let constant = self.a4_times_round_constants_b9[round];
105-
region.assign_fixed(
106-
|| "A4 * round_constant_b9",
107-
self.round_constant,
108-
offset,
109-
|| Ok(constant),
110-
)?;
111-
112-
let offset = 1;
113-
region.assign_advice(
114-
|| "lane 00 + A4 * round_constant_b9",
115-
self.lane00,
116-
offset,
117-
|| Ok(lane00.value().cloned().unwrap_or_default() + constant),
118-
)
119-
},
120-
)
121-
}
122-
123-
/// The 24-th round. Copy the flag `no_mixing` here.
124-
///
125-
/// If `no_mixing` is true: add `A4 * round_constant_b9`
126-
/// Otherwise, do nothing and return the orignal lane value in the next cell
127-
pub fn assign_b9_last_round(
128-
&self,
129-
layouter: &mut impl Layouter<F>,
130-
lane00: AssignedCell<F, F>,
131-
flag: AssignedCell<F, F>,
132-
) -> Result<AssignedCell<F, F>, Error> {
133-
layouter.assign_region(
134-
|| "IotaB9",
135-
|mut region| {
136-
let offset = 0;
137-
self.q_enable.enable(&mut region, offset)?;
138-
lane00.copy_advice(|| "lane 00", &mut region, self.lane00, offset)?;
139-
flag.copy_advice(|| "flag", &mut region, self.flag, offset)?;
140-
141-
let constant = self.a4_times_round_constants_b9[PERMUTATION - 1];
142-
region.assign_fixed(
143-
|| "A4 * round_constant_b9",
144-
self.round_constant,
145-
offset,
146-
|| Ok(constant),
147-
)?;
148-
149-
let offset = 1;
150-
region.assign_advice(
151-
|| "lane 00 + A4 * round_constant_b9",
152-
self.lane00,
153-
offset,
154-
|| {
155-
let flag = flag.value().cloned().unwrap_or_default();
156-
let lane00 = lane00.value().cloned().unwrap_or_default();
157-
Ok(lane00 + flag * constant)
158-
},
159-
)
160-
},
161-
)
162-
}
163-
164-
/// The 24-th round. Copy the flag `mixing` here.
165-
///
166-
/// If `mixing` is true: add round constant in base 13.
167-
/// Otherwise, do nothing and return the orignal lane value in the next cell
168-
pub fn assign_round_b13(
169-
&self,
170-
layouter: &mut impl Layouter<F>,
171-
lane00: AssignedCell<F, F>,
172-
flag: AssignedCell<F, F>,
173-
) -> Result<AssignedCell<F, F>, Error> {
174-
layouter.assign_region(
175-
|| "IotaB9",
176-
|mut region| {
177-
let offset = 0;
178-
self.q_enable.enable(&mut region, offset)?;
179-
lane00.copy_advice(|| "lane 00", &mut region, self.lane00, offset)?;
180-
flag.copy_advice(|| "flag", &mut region, self.flag, offset)?;
181-
182-
region.assign_fixed(
183-
|| "round_constant_b13",
184-
self.round_constant,
185-
offset,
186-
|| Ok(self.round_constant_b13),
187-
)?;
188-
189-
let offset = 1;
190-
region.assign_advice(
191-
|| "lane 00 + round_constant_b13",
192-
self.lane00,
193-
offset,
194-
|| {
195-
let lane00 = lane00.value().cloned().unwrap_or_default();
196-
let flag = flag.value().cloned().unwrap_or_default();
197-
Ok(lane00 + flag * self.round_constant_b13)
198-
},
199-
)
200-
},
201-
)
202-
}
20334
}

keccak256/src/permutation/mixing.rs

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,35 @@
11
use super::super::arith_helpers::*;
2+
use super::generic::GenericConfig;
23
use super::tables::FromBase9TableConfig;
3-
use super::{absorb::AbsorbConfig, base_conversion::BaseConversionConfig, iota::IotaConfig};
4+
use super::{absorb::AbsorbConfig, base_conversion::BaseConversionConfig, iota::IotaConstants};
45
use crate::common::*;
56
use crate::keccak_arith::KeccakFArith;
67
use eth_types::Field;
7-
use halo2_proofs::circuit::{AssignedCell, Region};
8-
use halo2_proofs::plonk::{Expression, Selector};
9-
use halo2_proofs::poly::Rotation;
108
use halo2_proofs::{
11-
circuit::Layouter,
12-
plonk::{Advice, Column, ConstraintSystem, Error},
9+
circuit::{AssignedCell, Layouter, Region},
10+
plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector},
11+
poly::Rotation,
1312
};
1413
use std::convert::TryInto;
1514

1615
#[derive(Clone, Debug)]
1716
pub struct MixingConfig<F> {
18-
iota_config: IotaConfig<F>,
17+
iota_constants: IotaConstants<F>,
1918
absorb_config: AbsorbConfig<F>,
2019
base_conv_config: BaseConversionConfig<F>,
2120
state: [Column<Advice>; 25],
2221
flag: Column<Advice>,
2322
q_flag: Selector,
2423
q_out_copy: Selector,
24+
generic: GenericConfig<F>,
2525
}
2626

2727
impl<F: Field> MixingConfig<F> {
2828
pub fn configure(
2929
meta: &mut ConstraintSystem<F>,
3030
table: &FromBase9TableConfig<F>,
31-
iota_config: IotaConfig<F>,
3231
state: [Column<Advice>; 25],
32+
generic: GenericConfig<F>,
3333
) -> MixingConfig<F> {
3434
// Allocate space for the flag column from which we will copy to all of
3535
// the sub-configs.
@@ -99,15 +99,17 @@ impl<F: Field> MixingConfig<F> {
9999
// the equality with the out_state of the permutation.
100100
[q_enable * ((left_side + right_side) - out_state)]
101101
});
102+
let iota_constants = IotaConstants::default();
102103

103104
MixingConfig {
104-
iota_config,
105+
iota_constants,
105106
absorb_config,
106107
base_conv_config,
107108
state,
108109
flag,
109110
q_flag,
110111
q_out_copy,
112+
generic,
111113
}
112114
}
113115

@@ -207,10 +209,14 @@ impl<F: Field> MixingConfig<F> {
207209
// IotaB9
208210
let non_mix_res = {
209211
let mut state = in_state.clone();
210-
state[0] = self.iota_config.assign_b9_last_round(
212+
// If `no_mixing` is true: add `A4 * round_constant_b9`
213+
// Otherwise, do nothing and return the orignal lane value in the
214+
// next cell
215+
state[0] = self.generic.conditional_add_const(
211216
layouter,
212217
state[0].clone(),
213218
negated_flag.clone(),
219+
self.iota_constants.a4_times_round_constants_b9[PERMUTATION - 1],
214220
)?;
215221
state
216222
};
@@ -238,9 +244,15 @@ impl<F: Field> MixingConfig<F> {
238244
let mix_res = {
239245
let mut base_conv_cells = base_conv_cells;
240246

241-
base_conv_cells[0] =
242-
self.iota_config
243-
.assign_round_b13(layouter, base_conv_cells[0].clone(), flag)?;
247+
// If `mixing` is true: add round constant in base 13.
248+
// Otherwise, do nothing and return the orignal lane value in the
249+
// next cell
250+
base_conv_cells[0] = self.generic.conditional_add_const(
251+
layouter,
252+
base_conv_cells[0].clone(),
253+
flag,
254+
self.iota_constants.round_constant_b13,
255+
)?;
244256
base_conv_cells
245257
};
246258

@@ -285,7 +297,6 @@ impl<F: Field> MixingConfig<F> {
285297
mod tests {
286298
use super::*;
287299
use crate::common::{State, ROUND_CONSTANTS};
288-
use crate::permutation::iota::IotaConfig;
289300
use halo2_proofs::circuit::Layouter;
290301
use halo2_proofs::pairing::bn256::Fr as Fp;
291302
use halo2_proofs::plonk::{ConstraintSystem, Error};
@@ -332,10 +343,11 @@ mod tests {
332343
.try_into()
333344
.unwrap();
334345
let fixed = meta.fixed_column();
335-
let iota_config = IotaConfig::configure(meta, state[0], state[1], fixed);
346+
let generic =
347+
GenericConfig::configure(meta, state[0..3].try_into().unwrap(), fixed);
336348

337349
MyConfig {
338-
mixing_conf: MixingConfig::configure(meta, &table, iota_config, state),
350+
mixing_conf: MixingConfig::configure(meta, &table, state, generic),
339351
table,
340352
}
341353
}

0 commit comments

Comments
 (0)