2021-06-18 19:44:54 -07:00
|
|
|
//! Gadget and chips for the Sinsemilla hash function.
|
|
|
|
use crate::circuit::gadget::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<F: FieldExt, const K: usize, const MAX_WORDS: usize>(Vec<MessagePiece<F, K>>);
|
|
|
|
|
|
|
|
impl<F: FieldExt + PrimeFieldBits, const K: usize, const MAX_WORDS: usize>
|
|
|
|
From<Vec<MessagePiece<F, K>>> for Message<F, K, MAX_WORDS>
|
|
|
|
{
|
|
|
|
fn from(pieces: Vec<MessagePiece<F, K>>) -> Self {
|
|
|
|
// A message cannot contain more than `MAX_WORDS` words.
|
|
|
|
assert!(pieces.iter().map(|piece| piece.num_words()).sum::<usize>() < MAX_WORDS);
|
|
|
|
Message(pieces)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F: FieldExt + PrimeFieldBits, const K: usize, const MAX_WORDS: usize> std::ops::Deref
|
|
|
|
for Message<F, K, MAX_WORDS>
|
|
|
|
{
|
|
|
|
type Target = [MessagePiece<F, K>];
|
|
|
|
|
|
|
|
fn deref(&self) -> &[MessagePiece<F, K>] {
|
|
|
|
&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`.
|
2021-12-01 04:51:33 -08:00
|
|
|
#[derive(Clone, Debug)]
|
2021-06-18 19:44:54 -07:00
|
|
|
pub struct MessagePiece<F: FieldExt, const K: usize> {
|
2021-06-21 08:27:13 -07:00
|
|
|
cell_value: CellValue<F>,
|
2021-06-20 03:30:43 -07:00
|
|
|
/// The number of K-bit words in this message piece.
|
2021-06-18 19:44:54 -07:00
|
|
|
num_words: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F: FieldExt + PrimeFieldBits, const K: usize> MessagePiece<F, K> {
|
2021-12-01 16:10:00 -08:00
|
|
|
pub fn new(cell: CellValue<F>, field_elem: Option<F>, num_words: usize) -> Self {
|
2021-06-18 19:44:54 -07:00
|
|
|
assert!(num_words * K < F::NUM_BITS as usize);
|
2021-06-21 08:27:13 -07:00
|
|
|
let cell_value = CellValue::new(cell, field_elem);
|
2021-06-18 19:44:54 -07:00
|
|
|
Self {
|
2021-06-21 08:27:13 -07:00
|
|
|
cell_value,
|
2021-06-18 19:44:54 -07:00
|
|
|
num_words,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn num_words(&self) -> usize {
|
|
|
|
self.num_words
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn cell(&self) -> Cell {
|
2021-06-21 08:27:13 -07:00
|
|
|
self.cell_value.cell()
|
2021-06-18 19:44:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn field_elem(&self) -> Option<F> {
|
2021-12-01 16:10:00 -08:00
|
|
|
self.cell_value.value().cloned()
|
2021-06-21 08:27:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn cell_value(&self) -> CellValue<F> {
|
2021-12-01 04:51:33 -08:00
|
|
|
self.cell_value.clone()
|
2021-06-18 19:44:54 -07:00
|
|
|
}
|
|
|
|
}
|