Skip to content

Commit 1e9fa9e

Browse files
Abstract out sinsemilla::message module
1 parent 2d39432 commit 1e9fa9e

File tree

4 files changed

+424
-323
lines changed

4 files changed

+424
-323
lines changed

src/circuit/gadget/sinsemilla.rs

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,18 @@ use halo2::{arithmetic::CurveAffine, circuit::Layouter, plonk::Error};
44
use std::fmt::Debug;
55

66
pub mod chip;
7+
mod message;
8+
79
pub use chip::{SinsemillaChip, SinsemillaConfig};
810

911
/// The set of circuit instructions required to use the [`Sinsemilla`](https://zcash.github.io/halo2/design/gadgets/sinsemilla.html) gadget.
1012
/// This trait is bounded on two constant parameters: `K`, the number of bits
1113
/// in each word accepted by the Sinsemilla hash, and `MAX_WORDS`, the maximum
1214
/// number of words that a single hash instance can process.
1315
pub trait SinsemillaInstructions<C: CurveAffine, const K: usize, const MAX_WORDS: usize> {
16+
/// A message composed of [`MessagePiece`]s.
17+
type Message: From<Vec<Self::MessagePiece>>;
18+
1419
/// A piece in a message containing a number of `K`-bit words.
1520
/// A [`MessagePiece`] fits in a single base field element,
1621
/// which means it can only contain up to `N` words, where
@@ -20,9 +25,6 @@ pub trait SinsemillaInstructions<C: CurveAffine, const K: usize, const MAX_WORDS
2025
/// up to `N = 25` words in a single base field element.
2126
type MessagePiece;
2227

23-
/// A cell in the circuit with an optional assigned value.
24-
type CellValue;
25-
2628
/// The x-coordinate of a point output of [`hash_to_point`].
2729
type X;
2830
/// A point output of [`hash_to_point`].
@@ -51,7 +53,7 @@ pub trait SinsemillaInstructions<C: CurveAffine, const K: usize, const MAX_WORDS
5153
layouter: impl Layouter<C::Base>,
5254
message: Vec<Option<bool>>,
5355
num_words: usize,
54-
) -> Result<Vec<Self::MessagePiece>, Error>;
56+
) -> Result<Self::Message, Error>;
5557

5658
/// Witness a message piece given a bitstring. Returns a [`MessagePiece`]
5759
/// encoding the given message.
@@ -84,17 +86,13 @@ pub trait SinsemillaInstructions<C: CurveAffine, const K: usize, const MAX_WORDS
8486
num_words: usize,
8587
) -> Result<Self::MessagePiece, Error>;
8688

87-
/// Prepare a message piece given a [`CellValue`] and the number of words
88-
/// encoded in the contained base field element.
89-
fn prepare_message_piece(cell: &Self::CellValue, num_words: usize) -> Self::MessagePiece;
90-
9189
/// Hashes a message to an ECC curve point.
9290
#[allow(non_snake_case)]
9391
fn hash_to_point(
9492
&self,
9593
layouter: impl Layouter<C::Base>,
9694
Q: C,
97-
message: Vec<Self::MessagePiece>,
95+
message: Self::Message,
9896
) -> Result<Self::Point, Error>;
9997

10098
/// Extracts the x-coordinate of the output of a Sinsemilla hash.
@@ -110,7 +108,7 @@ where
110108
SinsemillaChip: SinsemillaInstructions<C, K, MAX_WORDS> + Clone + Debug + Eq,
111109
{
112110
chip: SinsemillaChip,
113-
inner: Vec<SinsemillaChip::MessagePiece>,
111+
inner: SinsemillaChip::Message,
114112
}
115113

116114
impl<C: CurveAffine, SinsemillaChip, const K: usize, const MAX_WORDS: usize>
@@ -132,24 +130,9 @@ where
132130
fn from_pieces(chip: SinsemillaChip, pieces: Vec<SinsemillaChip::MessagePiece>) -> Self {
133131
Self {
134132
chip,
135-
inner: pieces,
133+
inner: pieces.into(),
136134
}
137135
}
138-
139-
/// Return the `MessagePiece`s contained in this `Message`.
140-
fn pieces(&self) -> &[SinsemillaChip::MessagePiece] {
141-
&self.inner
142-
}
143-
144-
/// Construct a `MessagePiece` given a vector of `CellValue`s and the
145-
/// number of words encoded in the contained base field elements.
146-
fn new_piece(
147-
_chip: SinsemillaChip,
148-
cell: &SinsemillaChip::CellValue,
149-
num_words: usize,
150-
) -> SinsemillaChip::MessagePiece {
151-
SinsemillaChip::prepare_message_piece(cell, num_words)
152-
}
153136
}
154137

155138
#[allow(non_snake_case)]
@@ -337,9 +320,12 @@ mod tests {
337320
SinsemillaInstructions,
338321
};
339322

340-
use crate::circuit::gadget::ecc::{
341-
chip::{EccChip, EccConfig},
342-
ScalarFixed,
323+
use crate::circuit::gadget::{
324+
ecc::{
325+
chip::{EccChip, EccConfig},
326+
ScalarFixed,
327+
},
328+
utilities::Var,
343329
};
344330

345331
use std::convert::TryInto;
@@ -432,7 +418,11 @@ mod tests {
432418
)?;
433419
let left = merkle_crh.hash_to_point(layouter.namespace(|| "left"), left)?;
434420
let left = left.extract_p();
435-
Message::new_piece(chip1.clone(), left.inner(), 25)
421+
chip1.witness_message_piece_field(
422+
layouter.namespace(|| "witness left piece"),
423+
left.inner().value(),
424+
25,
425+
)?
436426
};
437427

438428
// Right leaf
@@ -447,7 +437,11 @@ mod tests {
447437
)?;
448438
let right = merkle_crh.hash_to_point(layouter.namespace(|| "right"), right)?;
449439
let right = right.extract_p();
450-
Message::new_piece(chip1.clone(), right.inner(), 25)
440+
chip1.witness_message_piece_field(
441+
layouter.namespace(|| "witness left piece"),
442+
right.inner().value(),
443+
25,
444+
)?
451445
};
452446

453447
// Layer 0

src/circuit/gadget/sinsemilla/chip.rs

Lines changed: 20 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1-
use super::super::ecc::chip::{CellValue, EccPoint};
2-
use super::{CommitDomains, HashDomains, SinsemillaInstructions};
1+
use super::{
2+
message::{Message, MessagePiece},
3+
CommitDomains, HashDomains, SinsemillaInstructions,
4+
};
5+
use crate::circuit::gadget::{
6+
ecc::chip::EccPoint,
7+
utilities::{CellValue, Var},
8+
};
39

410
use crate::constants::OrchardFixedBasesFull;
511
use crate::primitives::sinsemilla::{
@@ -23,27 +29,6 @@ use generator_table::{GeneratorTableChip, GeneratorTableConfig};
2329

2430
mod hash_to_point;
2531

26-
/// A [`MessagePiece`] of some bitlength.
27-
///
28-
/// The piece must fit within a cell, which means its length cannot exceed
29-
/// the base field's `NUM_BITS`.
30-
#[derive(Clone, Debug)]
31-
pub struct MessagePiece<F: FieldExt> {
32-
cell: CellValue<F>,
33-
// The number of K-bit words in this message piece.
34-
num_words: usize,
35-
}
36-
37-
impl<F: FieldExt> MessagePiece<F> {
38-
fn new(cell: CellValue<F>, num_words: usize) -> Self {
39-
Self { cell, num_words }
40-
}
41-
42-
fn num_words(&self) -> usize {
43-
self.num_words
44-
}
45-
}
46-
4732
/// TODO: Configuration for the Sinsemilla hash chip
4833
#[derive(Clone, Debug)]
4934
pub struct SinsemillaConfig {
@@ -199,8 +184,8 @@ impl<C: CurveAffine, const K: usize, const MAX_WORDS: usize> SinsemillaChip<C, K
199184
impl<C: CurveAffine, const K: usize, const MAX_WORDS: usize> SinsemillaInstructions<C, K, MAX_WORDS>
200185
for SinsemillaChip<C, K, MAX_WORDS>
201186
{
202-
type MessagePiece = MessagePiece<C::Base>;
203-
type CellValue = CellValue<C::Base>;
187+
type Message = Message<C::Base, K, MAX_WORDS>;
188+
type MessagePiece = MessagePiece<C::Base, K>;
204189

205190
type X = CellValue<C::Base>;
206191
type Point = EccPoint<C>;
@@ -215,7 +200,7 @@ impl<C: CurveAffine, const K: usize, const MAX_WORDS: usize> SinsemillaInstructi
215200
mut layouter: impl Layouter<C::Base>,
216201
message: Vec<Option<bool>>,
217202
num_words: usize,
218-
) -> Result<Vec<Self::MessagePiece>, Error> {
203+
) -> Result<Self::Message, Error> {
219204
// Message must have at most `MAX_WORDS` words.
220205
assert!(num_words <= MAX_WORDS);
221206

@@ -224,17 +209,19 @@ impl<C: CurveAffine, const K: usize, const MAX_WORDS: usize> SinsemillaInstructi
224209

225210
// Message piece must be at most `ceil(C::Base::NUM_BITS / 10)` bits
226211
let piece_num_words = C::Base::NUM_BITS as usize / K;
227-
message
212+
let pieces: Result<Vec<_>, _> = message
228213
.chunks(piece_num_words * K)
229-
.map(|piece| {
214+
.map(|piece| -> Result<Self::MessagePiece, Error> {
230215
let num_words = (piece.len() + K - 1) / K;
231216
self.witness_message_piece_bitstring(
232217
layouter.namespace(|| "message piece"),
233218
piece.to_vec(),
234219
num_words,
235220
)
236221
})
237-
.collect()
222+
.collect();
223+
224+
pieces.map(|pieces| pieces.into())
238225
}
239226

240227
#[allow(non_snake_case)]
@@ -282,10 +269,7 @@ impl<C: CurveAffine, const K: usize, const MAX_WORDS: usize> SinsemillaInstructi
282269
0,
283270
|| piece_value.ok_or(Error::SynthesisError),
284271
)?;
285-
Ok(MessagePiece::new(
286-
CellValue::new(cell, piece_value),
287-
num_words,
288-
))
272+
Ok(MessagePiece::new(cell, piece_value, num_words))
289273
},
290274
)
291275
}
@@ -309,34 +293,19 @@ impl<C: CurveAffine, const K: usize, const MAX_WORDS: usize> SinsemillaInstructi
309293
)
310294
},
311295
)?;
312-
Ok(Self::prepare_message_piece(
313-
&CellValue::new(cell, value),
314-
num_words,
315-
))
316-
}
317-
318-
fn prepare_message_piece(cell: &Self::CellValue, length: usize) -> Self::MessagePiece {
319-
MessagePiece::new(cell.clone(), length)
296+
Ok(MessagePiece::new(cell, value, num_words))
320297
}
321298

322299
#[allow(non_snake_case)]
323300
fn hash_to_point(
324301
&self,
325302
mut layouter: impl Layouter<C::Base>,
326303
Q: C,
327-
message: Vec<Self::MessagePiece>,
304+
message: Self::Message,
328305
) -> Result<Self::Point, Error> {
329-
let config = self.config();
330306
layouter.assign_region(
331307
|| "hash_to_point",
332-
|mut region| {
333-
hash_to_point::hash_message::<C, K, MAX_WORDS>(
334-
&mut region,
335-
config.clone(),
336-
Q,
337-
&message,
338-
)
339-
},
308+
|mut region| self.hash_message(&mut region, Q, &message),
340309
)
341310
}
342311

0 commit comments

Comments
 (0)