sinsemilla::message.rs: Add message module.

This defines a Sinsemilla message in terms of pieces and subpieces.
This is useful when decomposing field elements and packing them
into K-bit messages.
This commit is contained in:
therealyingtong 2021-06-19 10:44:54 +08:00
parent af2ac762f4
commit e2859df4eb
2 changed files with 72 additions and 1 deletions

View File

@ -7,7 +7,7 @@ use halo2::{arithmetic::CurveAffine, circuit::Layouter, plonk::Error};
use std::fmt::Debug;
// pub mod chip;
// mod message;
mod message;
// pub use chip::{SinsemillaChip, SinsemillaConfig};

View File

@ -0,0 +1,71 @@
//! 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`.
#[derive(Copy, Clone, Debug)]
pub struct MessagePiece<F: FieldExt, const K: usize> {
cell: Cell,
field_elem: Option<F>,
// The number of K-bit words in this message piece.
num_words: usize,
}
#[allow(clippy::from_over_into)]
impl<F: FieldExt + PrimeFieldBits, const K: usize> Into<CellValue<F>> for MessagePiece<F, K> {
fn into(self) -> CellValue<F> {
CellValue::new(self.cell(), self.field_elem())
}
}
impl<F: FieldExt + PrimeFieldBits, const K: usize> MessagePiece<F, K> {
pub fn new(cell: Cell, field_elem: Option<F>, num_words: usize) -> Self {
assert!(num_words * K < F::NUM_BITS as usize);
Self {
cell,
field_elem,
num_words,
}
}
pub fn num_words(&self) -> usize {
self.num_words
}
pub fn cell(&self) -> Cell {
self.cell
}
pub fn field_elem(&self) -> Option<F> {
self.field_elem
}
}