PR feedback

This commit is contained in:
wborgeaud 2022-01-02 10:16:35 +01:00
parent 77a2fc6100
commit 7b03ebe1b8

View File

@ -1,3 +1,5 @@
use std::mem::size_of;
use keccak_hash::keccak;
use crate::hash::hash_types::{BytesHash, RichField};
@ -5,37 +7,49 @@ use crate::hash::hashing::{PlonkyPermutation, SPONGE_WIDTH};
use crate::plonk::config::Hasher;
use crate::util::serialization::Buffer;
/// Keccak-256 permutation used in the challenger.
/// Keccak-256 pseudo-permutation (not necessarily one-to-one) used in the challenger.
/// A state `input: [F; 12]` is sent to the field representation of `H(input) || H(H(input)) || H(H(H(input)))`
/// where `H` is the Keccak-256 hash.
pub struct KeccakPermutation;
impl<F: RichField> PlonkyPermutation<F> for KeccakPermutation {
fn permute(input: [F; SPONGE_WIDTH]) -> [F; SPONGE_WIDTH] {
// Fill a byte array with the little-endian representation of the field array.
let mut buffer = [0u8; SPONGE_WIDTH * std::mem::size_of::<u64>()];
for i in 0..SPONGE_WIDTH {
buffer[i * std::mem::size_of::<F>()..(i + 1) * std::mem::size_of::<F>()]
.copy_from_slice(&input[i].to_canonical_u64().to_le_bytes());
// Use rejection sampling so that if one of the `u64` values in the output is larger than
// the field order, we increment the nonce and start again.
'rejection_sampling: for nonce in 0u64.. {
// Fill a byte array with the little-endian representation of the field array.
let mut buffer = [0u8; (SPONGE_WIDTH + 1) * size_of::<u64>()];
for i in 0..SPONGE_WIDTH {
buffer[i * size_of::<u64>()..(i + 1) * size_of::<u64>()]
.copy_from_slice(&input[i].to_canonical_u64().to_le_bytes());
}
// Add the nonce at the end of the buffer.
buffer[SPONGE_WIDTH * size_of::<u64>()..].copy_from_slice(&nonce.to_le_bytes());
// Concatenate `H(input), H(H(input)), H(H(H(input)))`.
let permutated_input_bytes = {
let mut ans = [0u8; 96];
ans[0..32].copy_from_slice(&keccak(buffer).0);
ans[32..64].copy_from_slice(&keccak(keccak(buffer).0).0);
ans[64..96].copy_from_slice(&keccak(keccak(keccak(buffer).0).0).0);
ans
};
// Write the hashed byte array to a field array.
let mut permutated_input = [F::ZERO; SPONGE_WIDTH];
for i in 0..SPONGE_WIDTH {
let perm_u64 = u64::from_le_bytes(
permutated_input_bytes[i * size_of::<u64>()..(i + 1) * size_of::<u64>()]
.try_into()
.unwrap(),
);
if perm_u64 >= F::ORDER {
// If a value is larger than the field order, we break and start again with a new nonce.
continue 'rejection_sampling;
} else {
permutated_input[i] = F::from_canonical_u64(perm_u64);
}
}
return permutated_input;
}
// Concatenate `H(input), H(H(input)), H(H(H(input)))`.
let permutated_input_bytes = {
let mut ans = [0u8; 96];
ans[0..32].copy_from_slice(&keccak(buffer).0);
ans[32..64].copy_from_slice(&keccak(keccak(buffer).0).0);
ans[64..96].copy_from_slice(&keccak(keccak(keccak(buffer).0).0).0);
ans
};
// Write the hashed byte array to a field array.
let mut permutated_input = [F::ZERO; SPONGE_WIDTH];
for i in 0..SPONGE_WIDTH {
permutated_input[i] = F::from_noncanonical_u64(u64::from_le_bytes(
permutated_input_bytes
[i * std::mem::size_of::<F>()..(i + 1) * std::mem::size_of::<F>()]
.try_into()
.unwrap(),
));
}
permutated_input
panic!("Improbable.")
}
}