mirror of https://github.com/zcash/halo2.git
sinsemilla::chip.rs: Implement witness_message_* APIs.
witness_message() witnesses a full message given a bitstring. The other two APIs, witness_message_piece_bitstring() and witness_message_piece_field(), both witness a message piece, i.e. part of a message that fits within a single base field element. witness_message_piece_bitstring() takes in a bitstring, while witness_message_piece_field() takes in a field element. In the latter case, the number of words encoded must be specified.
This commit is contained in:
parent
74e617b46d
commit
7cddc9b587
|
@ -128,7 +128,26 @@ impl SinsemillaInstructions<pallas::Affine, { sinsemilla::K }, { sinsemilla::C }
|
|||
mut layouter: impl Layouter<pallas::Base>,
|
||||
message: Vec<Option<bool>>,
|
||||
) -> Result<Self::Message, Error> {
|
||||
todo!()
|
||||
// Message must be composed of `K`-bit words.
|
||||
assert_eq!(message.len() % sinsemilla::K, 0);
|
||||
|
||||
// Message must have at most `sinsemilla::C` words.
|
||||
assert!(message.len() / sinsemilla::K <= sinsemilla::C);
|
||||
|
||||
// Message piece must be at most `ceil(pallas::Base::NUM_BITS / sinsemilla::K)` bits
|
||||
let piece_num_words = pallas::Base::NUM_BITS as usize / sinsemilla::K;
|
||||
let pieces: Result<Vec<_>, _> = message
|
||||
.chunks(piece_num_words * sinsemilla::K)
|
||||
.enumerate()
|
||||
.map(|(i, piece)| -> Result<Self::MessagePiece, Error> {
|
||||
self.witness_message_piece_bitstring(
|
||||
layouter.namespace(|| format!("message piece {}", i)),
|
||||
piece,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
pieces.map(|pieces| pieces.into())
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
|
@ -137,7 +156,34 @@ impl SinsemillaInstructions<pallas::Affine, { sinsemilla::K }, { sinsemilla::C }
|
|||
layouter: impl Layouter<pallas::Base>,
|
||||
message_piece: &[Option<bool>],
|
||||
) -> Result<Self::MessagePiece, Error> {
|
||||
todo!()
|
||||
// Message must be composed of `K`-bit words.
|
||||
assert_eq!(message_piece.len() % sinsemilla::K, 0);
|
||||
let num_words = message_piece.len() / sinsemilla::K;
|
||||
|
||||
// Message piece must be at most `ceil(C::Base::NUM_BITS / sinsemilla::K)` bits
|
||||
let piece_max_num_words = pallas::Base::NUM_BITS as usize / sinsemilla::K;
|
||||
assert!(num_words <= piece_max_num_words as usize);
|
||||
|
||||
// Closure to parse a bitstring (little-endian) into a base field element.
|
||||
let to_base_field = |bits: &[Option<bool>]| -> Option<pallas::Base> {
|
||||
assert!(bits.len() <= pallas::Base::NUM_BITS as usize);
|
||||
|
||||
let bits: Option<Vec<bool>> = bits.iter().cloned().collect();
|
||||
let bytes: Option<Vec<u8>> = bits.map(|bits| {
|
||||
// Pad bits to 256 bits
|
||||
let pad_len = 256 - bits.len();
|
||||
let mut bits = bits;
|
||||
bits.extend_from_slice(&vec![false; pad_len]);
|
||||
|
||||
bits.chunks_exact(8)
|
||||
.map(|byte| byte.iter().rev().fold(0u8, |acc, bit| acc * 2 + *bit as u8))
|
||||
.collect()
|
||||
});
|
||||
bytes.map(|bytes| pallas::Base::from_bytes(&bytes.try_into().unwrap()).unwrap())
|
||||
};
|
||||
|
||||
let piece_value = to_base_field(message_piece);
|
||||
self.witness_message_piece_field(layouter, piece_value, num_words)
|
||||
}
|
||||
|
||||
fn witness_message_piece_field(
|
||||
|
@ -146,7 +192,20 @@ impl SinsemillaInstructions<pallas::Affine, { sinsemilla::K }, { sinsemilla::C }
|
|||
field_elem: Option<pallas::Base>,
|
||||
num_words: usize,
|
||||
) -> Result<Self::MessagePiece, Error> {
|
||||
todo!()
|
||||
let config = self.config().clone();
|
||||
|
||||
let cell = layouter.assign_region(
|
||||
|| "witness message piece",
|
||||
|mut region| {
|
||||
region.assign_advice(
|
||||
|| "witness message piece",
|
||||
config.bits,
|
||||
0,
|
||||
|| field_elem.ok_or(Error::SynthesisError),
|
||||
)
|
||||
},
|
||||
)?;
|
||||
Ok(MessagePiece::new(cell, field_elem, num_words))
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
|
|
Loading…
Reference in New Issue