//! Gadget and chips for the Sinsemilla hash function. use ff::{Field, PrimeFieldBits}; use halo2_proofs::circuit::{AssignedCell, Cell, Value}; use std::fmt::Debug; /// A [`Message`] composed of several [`MessagePiece`]s. #[derive(Clone, Debug)] pub struct Message(Vec>); impl From>> for Message { fn from(pieces: Vec>) -> Self { // A message cannot contain more than `MAX_WORDS` words. assert!(pieces.iter().map(|piece| piece.num_words()).sum::() < MAX_WORDS); Message(pieces) } } impl std::ops::Deref for Message { type Target = [MessagePiece]; fn deref(&self) -> &[MessagePiece] { &self.0 } } /// A [`MessagePiece`] of some bitlength. /// /// The piece must fit within a base field element, which means its length /// cannot exceed the base field's `NUM_BITS`. #[derive(Clone, Debug)] pub struct MessagePiece { cell_value: AssignedCell, /// The number of K-bit words in this message piece. num_words: usize, } impl MessagePiece { pub fn new(cell_value: AssignedCell, num_words: usize) -> Self { assert!(num_words * K < F::NUM_BITS as usize); Self { cell_value, num_words, } } pub fn num_words(&self) -> usize { self.num_words } pub fn cell(&self) -> Cell { self.cell_value.cell() } pub fn field_elem(&self) -> Value { self.cell_value.value().cloned() } pub fn cell_value(&self) -> AssignedCell { self.cell_value.clone() } }