Docfixes, variable renames, cleanups

Co-authored-by: Daira Hopwood <daira@jacaranda.org>
This commit is contained in:
therealyingtong 2021-06-28 17:06:39 +08:00
parent 32e564a963
commit d68eb6583d
3 changed files with 48 additions and 44 deletions

View File

@ -7,10 +7,12 @@ use pasta_curves::arithmetic::CurveAffine;
use super::{HashDomains, SinsemillaInstructions}; use super::{HashDomains, SinsemillaInstructions};
use crate::{ use crate::{
circuit::gadget::utilities::{cond_swap::CondSwapInstructions, UtilitiesInstructions}, circuit::gadget::utilities::{
cond_swap::CondSwapInstructions, transpose_option_array, UtilitiesInstructions,
},
spec::i2lebsp, spec::i2lebsp,
}; };
use std::{convert::TryInto, iter}; use std::iter;
mod chip; mod chip;
@ -28,14 +30,15 @@ pub trait MerkleInstructions<
+ UtilitiesInstructions<C::Base> + UtilitiesInstructions<C::Base>
+ Chip<C::Base> + Chip<C::Base>
{ {
/// Compute MerkleCRH for a given `layer`. The root is at `layer 0`, and the /// Compute MerkleCRH for a given `layer`. The hash that computes the root
/// leaves are at `layer MERKLE_DEPTH_ORCHARD` = `layer 32`. /// is at layer 0, and the hashes that are applied to two leaves are at
/// layer `MERKLE_DEPTH_ORCHARD - 1` = layer 31.
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn hash_layer( fn hash_layer(
&self, &self,
layouter: impl Layouter<C::Base>, layouter: impl Layouter<C::Base>,
Q: C, Q: C,
l_star: usize, l: usize,
left: Self::Var, left: Self::Var,
right: Self::Var, right: Self::Var,
) -> Result<Self::Var, Error>; ) -> Result<Self::Var, Error>;
@ -55,6 +58,7 @@ pub struct MerklePath<
chip_2: MerkleChip, chip_2: MerkleChip,
domain: MerkleChip::HashDomains, domain: MerkleChip::HashDomains,
leaf_pos: Option<u32>, leaf_pos: Option<u32>,
// The Merkle path is ordered from leaves to root.
path: Option<[C::Base; PATH_LENGTH]>, path: Option<[C::Base; PATH_LENGTH]>,
} }
@ -82,41 +86,26 @@ where
.chain(iter::repeat(self.chip_1.clone()).take(PATH_LENGTH / 2)) .chain(iter::repeat(self.chip_1.clone()).take(PATH_LENGTH / 2))
.chain(iter::repeat(self.chip_2.clone())); .chain(iter::repeat(self.chip_2.clone()));
let path = if let Some(path) = self.path { // The Merkle path is ordered from leaves to root, which is consistent with the
path.iter() // little-endian representation of `pos` below.
.map(|node| Some(*node)) let path = transpose_option_array(self.path);
.collect::<Vec<_>>()
.try_into()
.unwrap()
} else {
[None; PATH_LENGTH]
};
// Get position as a PATH_LENGTH-bit bitstring (little-endian bit order). // Get position as a PATH_LENGTH-bit bitstring (little-endian bit order).
let pos: [Option<bool>; PATH_LENGTH] = { let pos: [Option<bool>; PATH_LENGTH] = {
let pos: Option<[bool; PATH_LENGTH]> = self.leaf_pos.map(|pos| i2lebsp(pos as u64)); let pos: Option<[bool; PATH_LENGTH]> = self.leaf_pos.map(|pos| i2lebsp(pos as u64));
let pos: [Option<bool>; PATH_LENGTH] = if let Some(pos) = pos { transpose_option_array(pos)
pos.iter()
.map(|pos| Some(*pos))
.collect::<Vec<_>>()
.try_into()
.unwrap()
} else {
[None; PATH_LENGTH]
};
pos
}; };
let Q = self.domain.Q(); let Q = self.domain.Q();
let mut node = leaf; let mut node = leaf;
for (l_star, ((sibling, pos), chip)) in path.iter().zip(pos.iter()).zip(chips).enumerate() { for (l, ((sibling, pos), chip)) in path.iter().zip(pos.iter()).zip(chips).enumerate() {
// `l_star` = MERKLE_DEPTH_ORCHARD - layer - 1, which is the index obtained from // `l` = MERKLE_DEPTH_ORCHARD - layer - 1, which is the index obtained from
// enumerating this Merkle path (going from leaf to root). // enumerating this Merkle path (going from leaf to root).
// For example, when `layer = 31` (the first sibling on the Merkle path), // For example, when `layer = 31` (the first sibling on the Merkle path),
// we have `l_star` = 32 - 31 - 1 = 0. // we have `l` = 32 - 31 - 1 = 0.
// On the other hand, when `layer = 0` (the final sibling on the Merkle path), // On the other hand, when `layer = 0` (the final sibling on the Merkle path),
// we have `l_star` = 32 - 0 - 1 = 31. // we have `l` = 32 - 0 - 1 = 31.
let pair = { let pair = {
let pair = (node, *sibling); let pair = (node, *sibling);
@ -125,12 +114,12 @@ where
}; };
// Each `hash_layer` consists of 52 Sinsemilla words: // Each `hash_layer` consists of 52 Sinsemilla words:
// - l_star (10 bits) = 1 word // - l (10 bits) = 1 word
// - left (255 bits) || right (255 bits) = 51 words (510 bits) // - left (255 bits) || right (255 bits) = 51 words (510 bits)
node = chip.hash_layer( node = chip.hash_layer(
layouter.namespace(|| format!("hash l_star {}", l_star)), layouter.namespace(|| format!("hash l {}", l)),
Q, Q,
l_star, l,
pair.0, pair.0,
pair.1, pair.1,
)?; )?;
@ -296,14 +285,14 @@ pub mod tests {
// Compute the root // Compute the root
let mut node = leaf; let mut node = leaf;
for (l_star, (sibling, pos)) in path.iter().zip(pos_bool.iter()).enumerate() { for (l, (sibling, pos)) in path.iter().zip(pos_bool.iter()).enumerate() {
let (left, right) = if *pos { let (left, right) = if *pos {
(*sibling, node) (*sibling, node)
} else { } else {
(node, *sibling) (node, *sibling)
}; };
let l_star = i2lebsp::<10>(l_star as u64); let l_star = i2lebsp::<10>(l as u64);
let left: Vec<_> = left let left: Vec<_> = left
.to_le_bits() .to_le_bits()
.iter() .iter()

View File

@ -27,7 +27,7 @@ use std::{array, convert::TryInto};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct MerkleConfig { pub struct MerkleConfig {
advices: [Column<Advice>; 5], advices: [Column<Advice>; 5],
l_star_plus1: Column<Fixed>, l_plus_1: Column<Fixed>,
perm: Permutation, perm: Permutation,
lookup_config: LookupRangeCheckConfig<pallas::Base, { sinsemilla::K }>, lookup_config: LookupRangeCheckConfig<pallas::Base, { sinsemilla::K }>,
pub(super) cond_swap_config: CondSwapConfig, pub(super) cond_swap_config: CondSwapConfig,
@ -74,7 +74,7 @@ impl MerkleChip {
// - Disabling the entire decomposition gate (when set to zero) // - Disabling the entire decomposition gate (when set to zero)
// (i.e. replacing a Selector). // (i.e. replacing a Selector).
let l_star_plus1 = meta.fixed_column(); let l_plus_1 = meta.fixed_column();
// Check that pieces have been decomposed correctly for Sinsemilla hash. // Check that pieces have been decomposed correctly for Sinsemilla hash.
// <https://zips.z.cash/protocol/nu5.pdf#orchardmerklecrh> // <https://zips.z.cash/protocol/nu5.pdf#orchardmerklecrh>
@ -88,7 +88,7 @@ impl MerkleChip {
// 250 bits, 20 bits, and 250 bits respectively. // 250 bits, 20 bits, and 250 bits respectively.
// //
meta.create_gate("Decomposition check", |meta| { meta.create_gate("Decomposition check", |meta| {
let l_star_plus1_whole = meta.query_fixed(l_star_plus1, Rotation::cur()); let l_plus_1_whole = meta.query_fixed(l_plus_1, Rotation::cur());
let two_pow_5 = pallas::Base::from_u64(1 << 5); let two_pow_5 = pallas::Base::from_u64(1 << 5);
let two_pow_10 = two_pow_5.square(); let two_pow_10 = two_pow_5.square();
@ -111,7 +111,7 @@ impl MerkleChip {
// a_0 = a - (a_1 * 2^10) // a_0 = a - (a_1 * 2^10)
let a_0 = a_whole - a_1.clone() * pallas::Base::from_u64(1 << 10); let a_0 = a_whole - a_1.clone() * pallas::Base::from_u64(1 << 10);
let l_star_check = let l_star_check =
a_0 - (l_star_plus1_whole.clone() - Expression::Constant(pallas::Base::one())); a_0 - (l_plus_1_whole.clone() - Expression::Constant(pallas::Base::one()));
// b = b_0||b_1||b_2 // b = b_0||b_1||b_2
// = (bits 240..=249 of left) || (bits 250..=254 of left) || (bits 0..=4 of right) // = (bits 240..=249 of left) || (bits 250..=254 of left) || (bits 0..=4 of right)
@ -143,12 +143,12 @@ impl MerkleChip {
let right_check = b_2 + c_whole * two_pow_5 - right_node; let right_check = b_2 + c_whole * two_pow_5 - right_node;
array::IntoIter::new([l_star_check, left_check, right_check, b1_b2_check]) array::IntoIter::new([l_star_check, left_check, right_check, b1_b2_check])
.map(move |poly| l_star_plus1_whole.clone() * poly) .map(move |poly| l_plus_1_whole.clone() * poly)
}); });
MerkleConfig { MerkleConfig {
advices, advices,
l_star_plus1, l_plus_1,
perm: sinsemilla_config.perm.clone(), perm: sinsemilla_config.perm.clone(),
cond_swap_config, cond_swap_config,
lookup_config, lookup_config,
@ -268,13 +268,13 @@ impl MerkleInstructions<pallas::Affine, MERKLE_DEPTH_ORCHARD, { sinsemilla::K },
layouter.assign_region( layouter.assign_region(
|| "Check piece decomposition", || "Check piece decomposition",
|mut region| { |mut region| {
// Set the fixed column `l_star_plus1` to the current l_star + 1. // Set the fixed column `l_plus_1` to the current l_star + 1.
let l_star_plus1 = (l_star as u64) + 1; let l_plus_1 = (l_star as u64) + 1;
region.assign_fixed( region.assign_fixed(
|| format!("l_star_plus1 {}", l_star_plus1), || format!("l_plus_1 {}", l_plus_1),
config.l_star_plus1, config.l_plus_1,
0, 0,
|| Ok(pallas::Base::from_u64(l_star_plus1)), || Ok(pallas::Base::from_u64(l_plus_1)),
)?; )?;
// Offset 0 // Offset 0

View File

@ -3,6 +3,7 @@ use halo2::{
plonk::{Advice, Column, Error, Permutation}, plonk::{Advice, Column, Error, Permutation},
}; };
use pasta_curves::arithmetic::FieldExt; use pasta_curves::arithmetic::FieldExt;
use std::convert::TryInto;
pub(crate) mod cond_swap; pub(crate) mod cond_swap;
pub(crate) mod enable_flag; pub(crate) mod enable_flag;
@ -84,3 +85,17 @@ where
Ok(CellValue::new(cell, copy.value)) Ok(CellValue::new(cell, copy.value))
} }
pub fn transpose_option_array<T: Copy + std::fmt::Debug, const LEN: usize>(
option_array: Option<[T; LEN]>,
) -> [Option<T>; LEN] {
if let Some(arr) = option_array {
arr.iter()
.map(|el| Some(*el))
.collect::<Vec<_>>()
.try_into()
.unwrap()
} else {
[None; LEN]
}
}