//! Gadget and chips for the Sinsemilla hash function. use utilities::{CellValue, Var}; use ff::PrimeFieldBits; use halo2::{arithmetic::FieldExt, circuit::Cell}; 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(Copy, Clone, Debug)] pub struct MessagePiece { cell_value: CellValue, /// The number of K-bit words in this message piece. num_words: usize, } impl MessagePiece { pub fn new(cell: Cell, field_elem: Option, num_words: usize) -> Self { assert!(num_words * K < F::NUM_BITS as usize); let cell_value = CellValue::new(cell, field_elem); 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) -> Option { self.cell_value.value() } pub fn cell_value(&self) -> CellValue { self.cell_value } }