Switch to "overwrite mode" sponges

And fix a bug where the rate was assumed to be width - 1 (which was true in plonky 1).
This commit is contained in:
Daniel Lubarov 2021-04-10 21:32:11 -07:00
parent a14ddc3b03
commit 7d9bb073f4
2 changed files with 16 additions and 11 deletions

View File

@ -69,10 +69,12 @@ impl<F: Field> CircuitBuilder<F> {
let mut state = [zero; SPONGE_WIDTH];
// Absorb all input chunks.
for input_chunk in inputs.chunks(SPONGE_WIDTH - 1) {
for input_chunk in inputs.chunks(SPONGE_RATE) {
// Overwrite the first r elements with the inputs. This differs from a standard sponge,
// where we would xor or add in the inputs. This is a well-known variant, though,
// sometimes called "overwrite mode".
for i in 0..input_chunk.len() {
// TODO: These adds are wasteful. Maybe GMiMCGate should have separates wires to be added in.
state[i] = self.add(state[i], input_chunk[i]);
state[i] = input_chunk[i];
}
state = self.permute(state);
}
@ -80,7 +82,7 @@ impl<F: Field> CircuitBuilder<F> {
// Squeeze until we have the desired number of outputs.
let mut outputs = Vec::new();
loop {
for i in 0..(SPONGE_WIDTH - 1) {
for i in 0..SPONGE_RATE {
outputs.push(state[i]);
if outputs.len() == num_outputs {
return outputs;
@ -118,7 +120,7 @@ pub fn hash_n_to_m<F: Field>(mut inputs: Vec<F>, num_outputs: usize, pad: bool)
let mut state = [F::ZERO; SPONGE_WIDTH];
// Absorb all input chunks.
for input_chunk in inputs.chunks(SPONGE_WIDTH - 1) {
for input_chunk in inputs.chunks(SPONGE_RATE) {
for i in 0..input_chunk.len() {
state[i] += input_chunk[i];
}
@ -128,7 +130,7 @@ pub fn hash_n_to_m<F: Field>(mut inputs: Vec<F>, num_outputs: usize, pad: bool)
// Squeeze until we have the desired number of outputs.
let mut outputs = Vec::new();
loop {
for i in 0..(SPONGE_WIDTH - 1) {
for i in 0..SPONGE_RATE {
outputs.push(state[i]);
if outputs.len() == num_outputs {
return outputs;

View File

@ -79,9 +79,11 @@ impl<F: Field> Challenger<F> {
/// Absorb any buffered inputs. After calling this, the input buffer will be empty.
fn absorb_buffered_inputs(&mut self) {
for input_chunk in self.input_buffer.chunks(SPONGE_RATE) {
// Add the inputs to our sponge state.
// Overwrite the first r elements with the inputs. This differs from a standard sponge,
// where we would xor or add in the inputs. This is a well-known variant, though,
// sometimes called "overwrite mode".
for (i, &input) in input_chunk.iter().enumerate() {
self.sponge_state[i] = self.sponge_state[i] + input;
self.sponge_state[i] = input;
}
// Apply the permutation.
@ -177,10 +179,11 @@ impl RecursiveChallenger {
builder: &mut CircuitBuilder<F>,
) {
for input_chunk in self.input_buffer.chunks(SPONGE_RATE) {
// Add the inputs to our sponge state.
// Overwrite the first r elements with the inputs. This differs from a standard sponge,
// where we would xor or add in the inputs. This is a well-known variant, though,
// sometimes called "overwrite mode".
for (i, &input) in input_chunk.iter().enumerate() {
// TODO: These adds are wasteful. Maybe GMiMCGate should have separates wires to be added in.
self.sponge_state[i] = builder.add(self.sponge_state[i], input);
self.sponge_state[i] = input;
}
// Apply the permutation.