mirror of https://github.com/zcash/orchard.git
Docfixes, variable renames, cleanups
Co-authored-by: Daira Hopwood <daira@jacaranda.org>
This commit is contained in:
parent
32e564a963
commit
d68eb6583d
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue