Skip to content

Commit

Permalink
Docfixes, variable renames, cleanups
Browse files Browse the repository at this point in the history
Co-authored-by: Daira Hopwood <daira@jacaranda.org>
  • Loading branch information
therealyingtong and daira committed Jun 29, 2021
1 parent 32e564a commit d68eb65
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 44 deletions.
55 changes: 22 additions & 33 deletions src/circuit/gadget/sinsemilla/merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ use pasta_curves::arithmetic::CurveAffine;
use super::{HashDomains, SinsemillaInstructions};

use crate::{
circuit::gadget::utilities::{cond_swap::CondSwapInstructions, UtilitiesInstructions},
circuit::gadget::utilities::{
cond_swap::CondSwapInstructions, transpose_option_array, UtilitiesInstructions,
},
spec::i2lebsp,
};
use std::{convert::TryInto, iter};
use std::iter;

mod chip;

Expand All @@ -28,14 +30,15 @@ pub trait MerkleInstructions<
+ UtilitiesInstructions<C::Base>
+ Chip<C::Base>
{
/// Compute MerkleCRH for a given `layer`. The root is at `layer 0`, and the
/// leaves are at `layer MERKLE_DEPTH_ORCHARD` = `layer 32`.
/// Compute MerkleCRH for a given `layer`. The hash that computes the root
/// 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)]
fn hash_layer(
&self,
layouter: impl Layouter<C::Base>,
Q: C,
l_star: usize,
l: usize,
left: Self::Var,
right: Self::Var,
) -> Result<Self::Var, Error>;
Expand All @@ -55,6 +58,7 @@ pub struct MerklePath<
chip_2: MerkleChip,
domain: MerkleChip::HashDomains,
leaf_pos: Option<u32>,
// The Merkle path is ordered from leaves to root.
path: Option<[C::Base; PATH_LENGTH]>,
}

Expand Down Expand Up @@ -82,41 +86,26 @@ where
.chain(iter::repeat(self.chip_1.clone()).take(PATH_LENGTH / 2))
.chain(iter::repeat(self.chip_2.clone()));

let path = if let Some(path) = self.path {
path.iter()
.map(|node| Some(*node))
.collect::<Vec<_>>()
.try_into()
.unwrap()
} else {
[None; PATH_LENGTH]
};
// The Merkle path is ordered from leaves to root, which is consistent with the
// little-endian representation of `pos` below.
let path = transpose_option_array(self.path);

// Get position as a PATH_LENGTH-bit bitstring (little-endian bit order).
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] = if let Some(pos) = pos {
pos.iter()
.map(|pos| Some(*pos))
.collect::<Vec<_>>()
.try_into()
.unwrap()
} else {
[None; PATH_LENGTH]
};
pos
transpose_option_array(pos)
};

let Q = self.domain.Q();

let mut node = leaf;
for (l_star, ((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
for (l, ((sibling, pos), chip)) in path.iter().zip(pos.iter()).zip(chips).enumerate() {
// `l` = MERKLE_DEPTH_ORCHARD - layer - 1, which is the index obtained from
// enumerating this Merkle path (going from leaf to root).
// 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),
// we have `l_star` = 32 - 0 - 1 = 31.
// we have `l` = 32 - 0 - 1 = 31.
let pair = {
let pair = (node, *sibling);

Expand All @@ -125,12 +114,12 @@ where
};

// 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)
node = chip.hash_layer(
layouter.namespace(|| format!("hash l_star {}", l_star)),
layouter.namespace(|| format!("hash l {}", l)),
Q,
l_star,
l,
pair.0,
pair.1,
)?;
Expand Down Expand Up @@ -296,14 +285,14 @@ pub mod tests {

// Compute the root
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 {
(*sibling, node)
} else {
(node, *sibling)
};

let l_star = i2lebsp::<10>(l_star as u64);
let l_star = i2lebsp::<10>(l as u64);
let left: Vec<_> = left
.to_le_bits()
.iter()
Expand Down
22 changes: 11 additions & 11 deletions src/circuit/gadget/sinsemilla/merkle/chip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use std::{array, convert::TryInto};
#[derive(Clone, Debug)]
pub struct MerkleConfig {
advices: [Column<Advice>; 5],
l_star_plus1: Column<Fixed>,
l_plus_1: Column<Fixed>,
perm: Permutation,
lookup_config: LookupRangeCheckConfig<pallas::Base, { sinsemilla::K }>,
pub(super) cond_swap_config: CondSwapConfig,
Expand Down Expand Up @@ -74,7 +74,7 @@ impl MerkleChip {
// - Disabling the entire decomposition gate (when set to zero)
// (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.
// <https://zips.z.cash/protocol/nu5.pdf#orchardmerklecrh>
Expand All @@ -88,7 +88,7 @@ impl MerkleChip {
// 250 bits, 20 bits, and 250 bits respectively.
//
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_10 = two_pow_5.square();
Expand All @@ -111,7 +111,7 @@ impl MerkleChip {
// a_0 = a - (a_1 * 2^10)
let a_0 = a_whole - a_1.clone() * pallas::Base::from_u64(1 << 10);
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
// = (bits 240..=249 of left) || (bits 250..=254 of left) || (bits 0..=4 of right)
Expand Down Expand Up @@ -143,12 +143,12 @@ impl MerkleChip {
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])
.map(move |poly| l_star_plus1_whole.clone() * poly)
.map(move |poly| l_plus_1_whole.clone() * poly)
});

MerkleConfig {
advices,
l_star_plus1,
l_plus_1,
perm: sinsemilla_config.perm.clone(),
cond_swap_config,
lookup_config,
Expand Down Expand Up @@ -268,13 +268,13 @@ impl MerkleInstructions<pallas::Affine, MERKLE_DEPTH_ORCHARD, { sinsemilla::K },
layouter.assign_region(
|| "Check piece decomposition",
|mut region| {
// Set the fixed column `l_star_plus1` to the current l_star + 1.
let l_star_plus1 = (l_star as u64) + 1;
// Set the fixed column `l_plus_1` to the current l_star + 1.
let l_plus_1 = (l_star as u64) + 1;
region.assign_fixed(
|| format!("l_star_plus1 {}", l_star_plus1),
config.l_star_plus1,
|| format!("l_plus_1 {}", l_plus_1),
config.l_plus_1,
0,
|| Ok(pallas::Base::from_u64(l_star_plus1)),
|| Ok(pallas::Base::from_u64(l_plus_1)),
)?;

// Offset 0
Expand Down
15 changes: 15 additions & 0 deletions src/circuit/gadget/utilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use halo2::{
plonk::{Advice, Column, Error, Permutation},
};
use pasta_curves::arithmetic::FieldExt;
use std::convert::TryInto;

pub(crate) mod cond_swap;
pub(crate) mod enable_flag;
Expand Down Expand Up @@ -84,3 +85,17 @@ where

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]
}
}

0 comments on commit d68eb65

Please sign in to comment.