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>,
|
mut layouter: impl Layouter<pallas::Base>,
|
||||||
message: Vec<Option<bool>>,
|
message: Vec<Option<bool>>,
|
||||||
) -> Result<Self::Message, Error> {
|
) -> 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)]
|
#[allow(non_snake_case)]
|
||||||
|
@ -137,7 +156,34 @@ impl SinsemillaInstructions<pallas::Affine, { sinsemilla::K }, { sinsemilla::C }
|
||||||
layouter: impl Layouter<pallas::Base>,
|
layouter: impl Layouter<pallas::Base>,
|
||||||
message_piece: &[Option<bool>],
|
message_piece: &[Option<bool>],
|
||||||
) -> Result<Self::MessagePiece, Error> {
|
) -> 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(
|
fn witness_message_piece_field(
|
||||||
|
@ -146,7 +192,20 @@ impl SinsemillaInstructions<pallas::Affine, { sinsemilla::K }, { sinsemilla::C }
|
||||||
field_elem: Option<pallas::Base>,
|
field_elem: Option<pallas::Base>,
|
||||||
num_words: usize,
|
num_words: usize,
|
||||||
) -> Result<Self::MessagePiece, Error> {
|
) -> 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)]
|
#[allow(non_snake_case)]
|
||||||
|
|
Loading…
Reference in New Issue