diff --git a/stwo_cairo_verifier/src/channel.cairo b/stwo_cairo_verifier/src/channel.cairo index d5fcd799..7dde85df 100644 --- a/stwo_cairo_verifier/src/channel.cairo +++ b/stwo_cairo_verifier/src/channel.cairo @@ -1,10 +1,10 @@ use core::array::SpanTrait; use core::num::traits::{WrappingMul, WrappingSub}; -use core::poseidon::{hades_permutation, poseidon_hash_span}; +use core::poseidon::hades_permutation; use core::traits::DivRem; use crate::fields::m31::M31Trait; use crate::fields::qm31::QM31Trait; -use crate::utils::pack4; +use crate::utils::{pack4, poseidon_hash_span}; use crate::{BaseField, SecureField}; /// Equals `2^31`. diff --git a/stwo_cairo_verifier/src/utils.cairo b/stwo_cairo_verifier/src/utils.cairo index 02b16b47..3aa30a7e 100644 --- a/stwo_cairo_verifier/src/utils.cairo +++ b/stwo_cairo_verifier/src/utils.cairo @@ -3,8 +3,10 @@ use core::box::BoxTrait; use core::dict::Felt252Dict; use core::dict::Felt252DictEntryTrait; use core::dict::Felt252DictTrait; +use core::hash::HashStateTrait; use core::iter::{IntoIterator, Iterator}; use core::num::traits::BitSize; +use core::poseidon::{HashState, hades_permutation}; use core::traits::DivRem; use core::traits::PanicDestruct; use crate::BaseField; @@ -226,6 +228,36 @@ pub fn bit_reverse_index(mut index: usize, mut bits: u32) -> usize { result } +/// Computes the Poseidon hash on the given input. +/// +/// Applies the sponge construction to digest many elements. +/// To distinguish between use cases, the capacity element is initialized to 0. +/// To distinguish between different input sizes always pads with 1, and possibly with another 0 to +/// complete to an even-sized input. +// Copied from standard library. Removed gas counting. +pub fn poseidon_hash_span(mut span: Span) -> felt252 { + _poseidon_hash_span_inner((0, 0, 0), ref span) +} + +/// Helper function for poseidon_hash_span. +// Copied from standard library. Removed gas counting. +fn _poseidon_hash_span_inner( + state: (felt252, felt252, felt252), ref span: Span, +) -> felt252 { + let (s0, s1, s2) = state; + let x = *match span.pop_front() { + Option::Some(x) => x, + Option::None => { return HashState { s0, s1, s2, odd: false }.finalize(); }, + }; + let y = *match span.pop_front() { + Option::Some(y) => y, + Option::None => { return HashState { s0: s0 + x, s1, s2, odd: true }.finalize(); }, + }; + let next_state = hades_permutation(s0 + x, s1 + y, s2); + _poseidon_hash_span_inner(next_state, ref span) +} + + #[cfg(test)] mod tests { use super::{ArrayImpl, bit_reverse_index}; diff --git a/stwo_cairo_verifier/src/vcs/hasher.cairo b/stwo_cairo_verifier/src/vcs/hasher.cairo index b25d5435..4eb1d4aa 100644 --- a/stwo_cairo_verifier/src/vcs/hasher.cairo +++ b/stwo_cairo_verifier/src/vcs/hasher.cairo @@ -1,7 +1,8 @@ use core::array::ArrayTrait; use core::hash::HashStateTrait; -use core::poseidon::{HashState, hades_permutation, poseidon_hash_span}; +use core::poseidon::{HashState, hades_permutation}; use crate::BaseField; +use crate::utils::poseidon_hash_span; /// 8 M31 elements fit in a hash, since 31*8 = 242 < 252. const M31_ELEMENETS_IN_HASH: usize = 8;