Remove "final" round logic from poseidon::Pow5T3Chip

This was a bug in the Poseidon reference implementation, fixed in v1.1.
This commit is contained in:
Jack Grigg 2021-03-13 17:32:11 +13:00 committed by Jack Grigg
parent 40a19b429c
commit 01eb431f1f
1 changed files with 6 additions and 71 deletions

View File

@ -20,7 +20,6 @@ pub struct Pow5T3Config<F: FieldExt> {
rc_b: [Column<Fixed>; WIDTH], rc_b: [Column<Fixed>; WIDTH],
s_full: Selector, s_full: Selector,
s_partial: Selector, s_partial: Selector,
s_final: Selector,
half_full_rounds: usize, half_full_rounds: usize,
half_partial_rounds: usize, half_partial_rounds: usize,
@ -73,7 +72,6 @@ impl<F: FieldExt> Pow5T3Chip<F> {
let s_full = meta.selector(); let s_full = meta.selector();
let s_partial = meta.selector(); let s_partial = meta.selector();
let s_final = meta.selector();
let alpha = [5, 0, 0, 0]; let alpha = [5, 0, 0, 0];
let pow_5 = |v: Expression<F>| { let pow_5 = |v: Expression<F>| {
@ -153,34 +151,6 @@ impl<F: FieldExt> Pow5T3Chip<F> {
] ]
}); });
meta.create_gate("final full round", |meta| {
let cur = [
meta.query_advice(state[0], Rotation::cur()),
meta.query_advice(state[1], Rotation::cur()),
meta.query_advice(state[2], Rotation::cur()),
];
let next = [
meta.query_advice(state[0], Rotation::next()),
meta.query_advice(state[1], Rotation::next()),
meta.query_advice(state[2], Rotation::next()),
];
let rc = [
meta.query_fixed(rc_a[0], Rotation::cur()),
meta.query_fixed(rc_a[1], Rotation::cur()),
meta.query_fixed(rc_a[2], Rotation::cur()),
];
let s_final = meta.query_selector(s_final, Rotation::cur());
let final_full_round = |idx: usize| {
s_final.clone() * (pow_5(cur[idx].clone() + rc[idx].clone()) - next[idx].clone())
};
vec![
final_full_round(0),
final_full_round(1),
final_full_round(2),
]
});
Pow5T3Config { Pow5T3Config {
state, state,
state_permutation, state_permutation,
@ -189,7 +159,6 @@ impl<F: FieldExt> Pow5T3Chip<F> {
rc_b, rc_b,
s_full, s_full,
s_partial, s_partial,
s_final,
half_full_rounds, half_full_rounds,
half_partial_rounds, half_partial_rounds,
alpha, alpha,
@ -250,21 +219,12 @@ impl<F: FieldExt> PoseidonInstructions<F> for Pow5T3Chip<F> {
(0..config.half_full_rounds).fold(Ok(state), |res, r| { (0..config.half_full_rounds).fold(Ok(state), |res, r| {
res.and_then(|state| { res.and_then(|state| {
if r < config.half_full_rounds - 1 { state.full_round(
state.full_round( &mut region,
&mut region, &config,
&config, config.half_full_rounds + 2 * config.half_partial_rounds + r,
config.half_full_rounds + 2 * config.half_partial_rounds + r, config.half_full_rounds + config.half_partial_rounds + r,
config.half_full_rounds + config.half_partial_rounds + r, )
)
} else {
state.final_round(
&mut region,
&config,
config.half_full_rounds + 2 * config.half_partial_rounds + r,
config.half_full_rounds + config.half_partial_rounds + r,
)
}
}) })
}) })
}, },
@ -389,31 +349,6 @@ impl<F: FieldExt> Pow5T3State<F> {
}) })
} }
fn final_round(
self,
region: &mut Region<F>,
config: &Pow5T3Config<F>,
round: usize,
offset: usize,
) -> Result<Self, Error> {
Self::round(region, config, round, offset, config.s_final, |_| {
let mut new_state = self
.0
.iter()
.zip(config.round_constants[round].iter())
.map(|(word, rc)| word.value.map(|v| (v + rc).pow(&config.alpha)));
Ok((
round + 1,
[
new_state.next().unwrap(),
new_state.next().unwrap(),
new_state.next().unwrap(),
],
))
})
}
fn load( fn load(
region: &mut Region<F>, region: &mut Region<F>,
config: &Pow5T3Config<F>, config: &Pow5T3Config<F>,