in crypto/src/hash/rescue/rp64_256/mod.rs [212:245]
fn hash_elements<E: FieldElement<BaseField = Self::BaseField>>(elements: &[E]) -> Self::Digest {
// convert the elements into a list of base field elements
let elements = E::as_base_elements(elements);
// initialize state to all zeros, except for the last element of the capacity part, which
// is set to the number of elements to be hashed. this is done so that adding zero elements
// at the end of the list always results in a different hash.
let mut state = [BaseElement::ZERO; STATE_WIDTH];
state[CAPACITY_RANGE.start] = BaseElement::new(elements.len() as u64);
// absorb elements into the state one by one until the rate portion of the state is filled
// up; then apply the Rescue permutation and start absorbing again; repeat until all
// elements have been absorbed
let mut i = 0;
for &element in elements.iter() {
state[RATE_RANGE.start + i] += element;
i += 1;
if i % RATE_WIDTH == 0 {
Self::apply_permutation(&mut state);
i = 0;
}
}
// if we absorbed some elements but didn't apply a permutation to them (would happen when
// the number of elements is not a multiple of RATE_WIDTH), apply the Rescue permutation.
// we don't need to apply any extra padding because we injected total number of elements
// in the input list into the capacity portion of the state during initialization.
if i > 0 {
Self::apply_permutation(&mut state);
}
// return the first 4 elements of the state as hash result
ElementDigest::new(state[DIGEST_RANGE].try_into().unwrap())
}