Merge pull request #43 from zcash/constants

Add Orchard constants
This commit is contained in:
str4d 2021-05-18 20:44:59 +01:00 committed by GitHub
commit 7109153e88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 27797 additions and 62 deletions

View File

@ -20,6 +20,7 @@ rustdoc-args = [ "--html-in-header", "katex-header.html" ]
[dependencies]
aes = "0.6"
arrayvec = "0.7.0"
bitvec = "0.20"
blake2b_simd = "0.5"
ff = "0.9"
@ -33,7 +34,7 @@ subtle = "2.3"
[dependencies.halo2]
git = "https://github.com/zcash/halo2.git"
rev = "6acacf1aca12f34fc311aa59056e40adc0e6d8bd"
rev = "cae6f6af725cf1f5bc94e126a0b41e9ac602a302"
[dependencies.pasta_curves]
git = "https://github.com/zcash/pasta_curves.git"

View File

@ -0,0 +1,7 @@
# Seeds for failure cases proptest has generated in the past. It is
# automatically read and these particular cases re-run before any
# novel cases are generated.
#
# It is recommended to check this file in to source control so that
# everyone who runs the test benefits from these saved cases.
cc 251d6e9f7ad2f5cd8679dec6b69aa9c879baae8742791b19669c136aef12deac # shrinks to scalar = 0x0000000000000000000000000000000000000000000000000000000000000000, window_num_bits = 6

View File

@ -1,140 +1,378 @@
//! Gadgets for elliptic curve operations.
use std::fmt;
use ff::Field;
use std::fmt::Debug;
use halo2::{
arithmetic::CurveAffine,
arithmetic::{CurveAffine, FieldExt},
circuit::{Chip, Layouter},
plonk::Error,
};
/// Trait allowing circuit's fixed points to be enumerated.
pub trait FixedPoints<C: CurveAffine>: Clone + fmt::Debug {}
/// The set of circuit instructions required to use the ECC gadgets.
pub trait EccInstructions<C: CurveAffine>: Chip<Field = C::Base> {
/// Variable representing an element of the elliptic curve's scalar field.
type Scalar: Clone + fmt::Debug;
pub trait EccInstructions<C: CurveAffine>: Chip<C::Base> {
/// Variable representing an element of the elliptic curve's base field, that
/// is used as a scalar in variable-base scalar mul.
///
/// It is not true in general that a scalar field element fits in a curve's
/// base field, and in particular it is untrue for the Pallas curve, whose
/// scalar field `Fq` is larger than its base field `Fp`.
///
/// However, the only use of variable-base scalar mul in the Orchard protocol
/// is in deriving diversified addresses `[ivk] g_d`, and `ivk` is guaranteed
/// to be in the base field of the curve. (See non-normative notes in
/// https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents.)
type ScalarVar: Clone + Debug;
/// Variable representing a full-width element of the elliptic curve's
/// scalar field, to be used for fixed-base scalar mul.
type ScalarFixed: Clone + Debug;
/// Variable representing a signed short element of the elliptic curve's
/// scalar field, to be used for fixed-base scalar mul.
///
/// A `ScalarFixedShort` must be in the range [-(2^64 - 1), 2^64 - 1].
type ScalarFixedShort: Clone + Debug;
/// Variable representing an elliptic curve point.
type Point: Clone + fmt::Debug;
type Point: Clone + Debug;
/// Variable representing the affine short Weierstrass x-coordinate of an
/// elliptic curve point.
type X: Clone + Debug;
/// Variable representing the set of fixed bases in the circuit.
type FixedPoints: FixedPoints<C>;
type FixedPoints: Clone + Debug;
/// Variable representing the set of fixed bases to be used in scalar
/// multiplication with a short signed exponent.
type FixedPointsShort: Clone + Debug;
/// Variable representing a fixed elliptic curve point (constant in the circuit).
type FixedPoint: Clone + fmt::Debug;
type FixedPoint: Clone + Debug;
/// Variable representing a fixed elliptic curve point (constant in the circuit)
/// to be used in scalar multiplication with a short signed exponent.
type FixedPointShort: Clone + Debug;
/// Witnesses the given scalar as a private input to the circuit.
fn witness_scalar(
layouter: &mut impl Layouter<Self>,
/// Witnesses the given base field element as a private input to the circuit
/// for variable-base scalar mul.
fn witness_scalar_var(
&self,
layouter: &mut impl Layouter<C::Base>,
value: Option<C::Base>,
) -> Result<Self::ScalarVar, Error>;
/// Witnesses the given full-width scalar as a private input to the circuit
/// for fixed-base scalar mul.
fn witness_scalar_fixed(
&self,
layouter: &mut impl Layouter<C::Base>,
value: Option<C::Scalar>,
) -> Result<Self::Scalar, Error>;
) -> Result<Self::ScalarFixed, Error>;
/// Witnesses the given signed short scalar as a private input to the circuit
/// for fixed-base scalar mul.
fn witness_scalar_fixed_short(
&self,
layouter: &mut impl Layouter<C::Base>,
value: Option<C::Scalar>,
) -> Result<Self::ScalarFixedShort, Error>;
/// Witnesses the given point as a private input to the circuit.
fn witness_point(
layouter: &mut impl Layouter<Self>,
&self,
layouter: &mut impl Layouter<C::Base>,
value: Option<C>,
) -> Result<Self::Point, Error>;
/// Gets a fixed point into the circuit.
fn get_fixed(
layouter: &mut impl Layouter<Self>,
fixed_points: Self::FixedPoints,
) -> Result<Self::FixedPoint, Error>;
/// Extracts the x-coordinate of a point.
fn extract_p(point: &Self::Point) -> &Self::X;
/// Performs point addition, returning `a + b`.
/// Returns a fixed point that had been previously loaded into the circuit.
/// The pre-loaded cells are used to set up equality constraints in other
/// parts of the circuit where the fixed base is used.
fn get_fixed(&self, fixed_points: Self::FixedPoints) -> Result<Self::FixedPoint, Error>;
/// Returns a fixed point to be used in scalar multiplication with a signed
/// short exponent.
fn get_fixed_short(
&self,
fixed_points: Self::FixedPointsShort,
) -> Result<Self::FixedPointShort, Error>;
/// Performs incomplete point addition, returning `a + b`.
///
/// This returns an error in exceptional cases.
fn add_incomplete(
&self,
layouter: &mut impl Layouter<C::Base>,
a: &Self::Point,
b: &Self::Point,
) -> Result<Self::Point, Error>;
/// Performs complete point addition, returning `a + b`.
fn add(
layouter: &mut impl Layouter<Self>,
&self,
layouter: &mut impl Layouter<C::Base>,
a: &Self::Point,
b: &Self::Point,
) -> Result<Self::Point, Error>;
/// Performs point doubling, returning `[2] a`.
fn double(layouter: &mut impl Layouter<Self>, a: &Self::Point) -> Result<Self::Point, Error>;
fn double(
&self,
layouter: &mut impl Layouter<C::Base>,
a: &Self::Point,
) -> Result<Self::Point, Error>;
/// Performs variable-base scalar multiplication, returning `[scalar] base`.
fn mul(
layouter: &mut impl Layouter<Self>,
scalar: &Self::Scalar,
&self,
layouter: &mut impl Layouter<C::Base>,
scalar: &Self::ScalarVar,
base: &Self::Point,
) -> Result<Self::Point, Error>;
/// Performs fixed-base scalar multiplication, returning `[scalar] base`.
/// Performs fixed-base scalar multiplication using a full-width scalar, returning `[scalar] base`.
fn mul_fixed(
layouter: &mut impl Layouter<Self>,
scalar: &Self::Scalar,
&self,
layouter: &mut impl Layouter<C::Base>,
scalar: &Self::ScalarFixed,
base: &Self::FixedPoint,
) -> Result<Self::Point, Error>;
/// Performs fixed-base scalar multiplication using a short signed scalar, returning `[scalar] base`.
fn mul_fixed_short(
&self,
layouter: &mut impl Layouter<C::Base>,
scalar: &Self::ScalarFixedShort,
base: &Self::FixedPointShort,
) -> Result<Self::Point, Error>;
}
/// An element of the given elliptic curve's scalar field.
/// An element of the given elliptic curve's base field, that is used as a scalar
/// in variable-base scalar mul.
///
/// It is not true in general that a scalar field element fits in a curve's
/// base field, and in particular it is untrue for the Pallas curve, whose
/// scalar field `Fq` is larger than its base field `Fp`.
///
/// However, the only use of variable-base scalar mul in the Orchard protocol
/// is in deriving diversified addresses `[ivk] g_d`, and `ivk` is guaranteed
/// to be in the base field of the curve. (See non-normative notes in
/// https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents.)
#[derive(Debug)]
pub struct Scalar<C: CurveAffine, EccChip: EccInstructions<C>> {
inner: EccChip::Scalar,
pub struct ScalarVar<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug + Eq> {
chip: EccChip,
inner: EccChip::ScalarVar,
}
impl<C: CurveAffine, EccChip: EccInstructions<C>> Scalar<C, EccChip> {
/// Constructs a new point with the given value.
impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug + Eq> ScalarVar<C, EccChip> {
/// Constructs a new ScalarVar with the given value.
pub fn new(
mut layouter: impl Layouter<EccChip>,
chip: EccChip,
mut layouter: impl Layouter<C::Base>,
value: Option<C::Base>,
) -> Result<Self, Error> {
chip.witness_scalar_var(&mut layouter, value)
.map(|inner| ScalarVar { chip, inner })
}
}
/// A full-width element of the given elliptic curve's scalar field, to be used for fixed-base scalar mul.
#[derive(Debug)]
pub struct ScalarFixed<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug + Eq> {
chip: EccChip,
inner: EccChip::ScalarFixed,
}
impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug + Eq> ScalarFixed<C, EccChip> {
/// Constructs a new ScalarFixed with the given value.
pub fn new(
chip: EccChip,
mut layouter: impl Layouter<C::Base>,
value: Option<C::Scalar>,
) -> Result<Self, Error> {
EccChip::witness_scalar(&mut layouter, value).map(|inner| Scalar { inner })
chip.witness_scalar_fixed(&mut layouter, value)
.map(|inner| ScalarFixed { chip, inner })
}
}
/// A signed short element of the given elliptic curve's scalar field, to be used for fixed-base scalar mul.
#[derive(Debug)]
pub struct ScalarFixedShort<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug + Eq> {
chip: EccChip,
inner: EccChip::ScalarFixedShort,
}
impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug + Eq>
ScalarFixedShort<C, EccChip>
{
/// Constructs a new ScalarFixedShort with the given value.
///
/// # Panics
///
/// The short scalar must be in the range [-(2^64 - 1), (2^64 - 1)].
pub fn new(
chip: EccChip,
mut layouter: impl Layouter<C::Base>,
value: Option<C::Scalar>,
) -> Result<Self, Error> {
// Check that the scalar is in the range [-(2^64 - 1), (2^64 - 1)]
if let Some(value) = value {
let mut sign = C::Scalar::one();
// T = (p-1) / 2
let t = (C::Scalar::zero() - C::Scalar::one()) * C::Scalar::TWO_INV;
if value > t {
sign = -sign;
}
let magnitude = value * sign;
assert!(magnitude < C::Scalar::from_u128(1 << 64));
}
chip.witness_scalar_fixed_short(&mut layouter, value)
.map(|inner| ScalarFixedShort { chip, inner })
}
}
/// An elliptic curve point over the given curve.
#[derive(Debug)]
pub struct Point<C: CurveAffine, EccChip: EccInstructions<C>> {
pub struct Point<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug + Eq> {
chip: EccChip,
inner: EccChip::Point,
}
impl<C: CurveAffine, EccChip: EccInstructions<C>> Point<C, EccChip> {
impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug + Eq> Point<C, EccChip> {
/// Constructs a new point with the given value.
pub fn new(mut layouter: impl Layouter<EccChip>, value: Option<C>) -> Result<Self, Error> {
EccChip::witness_point(&mut layouter, value).map(|inner| Point { inner })
pub fn new(
chip: EccChip,
mut layouter: impl Layouter<C::Base>,
value: Option<C>,
) -> Result<Self, Error> {
let point = chip.witness_point(&mut layouter, value);
point.map(|inner| Point { chip, inner })
}
/// Returns `self + other`.
pub fn add(&self, mut layouter: impl Layouter<EccChip>, other: &Self) -> Result<Self, Error> {
EccChip::add(&mut layouter, &self.inner, &other.inner).map(|inner| Point { inner })
/// Extracts the x-coordinate of a point.
pub fn extract_p(&self) -> X<C, EccChip> {
X::from_inner(self.chip.clone(), EccChip::extract_p(&self.inner).clone())
}
/// Returns `[2] self`.
pub fn double(&self, mut layouter: impl Layouter<EccChip>) -> Result<Self, Error> {
EccChip::double(&mut layouter, &self.inner).map(|inner| Point { inner })
/// Wraps the given point (obtained directly from an instruction) in a gadget.
pub fn from_inner(chip: EccChip, inner: EccChip::Point) -> Self {
Point { chip, inner }
}
/// Returns `self + other` using complete addition.
pub fn add(&self, mut layouter: impl Layouter<C::Base>, other: &Self) -> Result<Self, Error> {
assert_eq!(self.chip, other.chip);
self.chip
.add(&mut layouter, &self.inner, &other.inner)
.map(|inner| Point {
chip: self.chip.clone(),
inner,
})
}
/// Returns `self + other` using incomplete addition.
pub fn add_incomplete(
&self,
mut layouter: impl Layouter<C::Base>,
other: &Self,
) -> Result<Self, Error> {
assert_eq!(self.chip, other.chip);
self.chip
.add_incomplete(&mut layouter, &self.inner, &other.inner)
.map(|inner| Point {
chip: self.chip.clone(),
inner,
})
}
/// Returns `[by] self`.
pub fn mul(
&self,
mut layouter: impl Layouter<EccChip>,
by: &Scalar<C, EccChip>,
mut layouter: impl Layouter<C::Base>,
by: &ScalarVar<C, EccChip>,
) -> Result<Self, Error> {
EccChip::mul(&mut layouter, &by.inner, &self.inner).map(|inner| Point { inner })
assert_eq!(self.chip, by.chip);
self.chip
.mul(&mut layouter, &by.inner, &self.inner)
.map(|inner| Point {
chip: self.chip.clone(),
inner,
})
}
}
/// A constant elliptic curve point over the given curve, for which scalar multiplication
/// is more efficient.
/// The affine short Weierstrass x-coordinate of an elliptic curve point over the
/// given curve.
#[derive(Debug)]
pub struct FixedPoint<C: CurveAffine, EccChip: EccInstructions<C>> {
pub struct X<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug + Eq> {
chip: EccChip,
inner: EccChip::X,
}
impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug + Eq> X<C, EccChip> {
/// Wraps the given x-coordinate (obtained directly from an instruction) in a gadget.
pub fn from_inner(chip: EccChip, inner: EccChip::X) -> Self {
X { chip, inner }
}
}
/// A constant elliptic curve point over the given curve, for which window tables have
/// been provided to make scalar multiplication more efficient.
#[derive(Clone, Debug)]
pub struct FixedPoint<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug + Eq> {
chip: EccChip,
inner: EccChip::FixedPoint,
}
impl<C: CurveAffine, EccChip: EccInstructions<C>> FixedPoint<C, EccChip> {
impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug + Eq> FixedPoint<C, EccChip> {
/// Gets a reference to the specified fixed point in the circuit.
pub fn get(
mut layouter: impl Layouter<EccChip>,
point: EccChip::FixedPoints,
) -> Result<Self, Error> {
EccChip::get_fixed(&mut layouter, point).map(|inner| FixedPoint { inner })
pub fn get(chip: EccChip, point: EccChip::FixedPoints) -> Result<Self, Error> {
chip.get_fixed(point)
.map(|inner| FixedPoint { chip, inner })
}
/// Returns `[by] self`.
pub fn mul(
&self,
mut layouter: impl Layouter<EccChip>,
by: &Scalar<C, EccChip>,
mut layouter: impl Layouter<C::Base>,
by: &ScalarFixed<C, EccChip>,
) -> Result<Point<C, EccChip>, Error> {
EccChip::mul_fixed(&mut layouter, &by.inner, &self.inner).map(|inner| Point { inner })
assert_eq!(self.chip, by.chip);
self.chip
.mul_fixed(&mut layouter, &by.inner, &self.inner)
.map(|inner| Point {
chip: self.chip.clone(),
inner,
})
}
}
/// A constant elliptic curve point over the given curve, used in scalar multiplication
/// with a short signed exponent
#[derive(Clone, Debug)]
pub struct FixedPointShort<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug + Eq> {
chip: EccChip,
inner: EccChip::FixedPointShort,
}
impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug + Eq> FixedPointShort<C, EccChip> {
/// Gets a reference to the specified fixed point in the circuit.
pub fn get(chip: EccChip, point: EccChip::FixedPointsShort) -> Result<Self, Error> {
chip.get_fixed_short(point)
.map(|inner| FixedPointShort { chip, inner })
}
/// Returns `[by] self`.
pub fn mul(
&self,
mut layouter: impl Layouter<C::Base>,
by: &ScalarFixedShort<C, EccChip>,
) -> Result<Point<C, EccChip>, Error> {
assert_eq!(self.chip, by.chip);
self.chip
.mul_fixed_short(&mut layouter, &by.inner, &self.inner)
.map(|inner| Point {
chip: self.chip.clone(),
inner,
})
}
}

View File

@ -1,4 +1,281 @@
//! Constants used in the Orchard protocol.
use arrayvec::ArrayVec;
use ff::{Field, PrimeField};
use group::Curve;
use halo2::{
arithmetic::{lagrange_interpolate, CurveAffine, FieldExt},
pasta::pallas,
};
pub mod commit_ivk_r;
pub mod note_commit_r;
pub mod nullifier_k;
pub mod value_commit_r;
pub mod value_commit_v;
pub mod util;
/// $\ell^\mathsf{Orchard}_\mathsf{base}$
pub(crate) const L_ORCHARD_BASE: usize = 255;
/// $\ell_\mathsf{value}$
pub(crate) const L_VALUE: usize = 64;
/// SWU hash-to-curve personalization for the spending key base point and
/// the nullifier base point K^Orchard
pub const ORCHARD_PERSONALIZATION: &str = "z.cash:Orchard";
/// SWU hash-to-curve personalization for the group hash for key diversification
pub const KEY_DIVERSIFICATION_PERSONALIZATION: &str = "z.cash:Orchard-gd";
/// SWU hash-to-curve personalization for the value commitment generator
pub const VALUE_COMMITMENT_PERSONALIZATION: &str = "z.cash:Orchard-cv";
/// SWU hash-to-curve personalization for the note commitment generator
pub const NOTE_COMMITMENT_PERSONALIZATION: &str = "z.cash:Orchard-NoteCommit";
/// SWU hash-to-curve personalization for the IVK commitment generator
pub const COMMIT_IVK_PERSONALIZATION: &str = "z.cash:Orchard-CommitIvk";
/// SWU hash-to-curve personalization for the Merkle CRH generator
pub const MERKLE_CRH_PERSONALIZATION: &str = "z.cash:Orchard-MerkleCRH";
/// Window size for fixed-base scalar multiplication
pub const FIXED_BASE_WINDOW_SIZE: usize = 3;
/// $2^{`FIXED_BASE_WINDOW_SIZE`}$
pub const H: usize = 1 << FIXED_BASE_WINDOW_SIZE;
/// Number of windows for a full-width scalar
pub const NUM_WINDOWS: usize =
(pallas::Base::NUM_BITS as usize + FIXED_BASE_WINDOW_SIZE - 1) / FIXED_BASE_WINDOW_SIZE;
/// Number of windows for a short signed scalar
pub const NUM_WINDOWS_SHORT: usize =
(L_VALUE + FIXED_BASE_WINDOW_SIZE - 1) / FIXED_BASE_WINDOW_SIZE;
/// Number of bits for which complete addition needs to be used in variable-base
/// scalar multiplication
pub const NUM_COMPLETE_BITS: usize = 3;
#[derive(Copy, Clone, Debug)]
pub struct CommitIvkR<C: CurveAffine>(pub OrchardFixedBase<C>);
#[derive(Copy, Clone, Debug)]
pub struct NoteCommitR<C: CurveAffine>(pub OrchardFixedBase<C>);
#[derive(Copy, Clone, Debug)]
pub struct NullifierK<C: CurveAffine>(pub OrchardFixedBase<C>);
#[derive(Copy, Clone, Debug)]
pub struct ValueCommitR<C: CurveAffine>(pub OrchardFixedBase<C>);
#[derive(Copy, Clone, Debug)]
pub struct ValueCommitV<C: CurveAffine>(pub OrchardFixedBase<C>);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct OrchardFixedBase<C: CurveAffine>(C);
impl<C: CurveAffine> OrchardFixedBase<C> {
pub fn new(generator: C) -> Self {
OrchardFixedBase(generator)
}
pub fn value(&self) -> C {
self.0
}
}
pub trait FixedBase<C: CurveAffine> {
/// For each fixed base, we calculate its scalar multiples in three-bit windows.
/// Each window will have $2^3 = 8$ points.
fn compute_window_table(&self, num_windows: usize) -> Vec<[C; H]>;
/// For each window, we interpolate the $x$-coordinate.
/// Here, we pre-compute and store the coefficients of the interpolation polynomial.
fn compute_lagrange_coeffs(&self, num_windows: usize) -> Vec<[C::Base; H]>;
/// For each window, $z$ is a field element such that for each point $(x, y)$ in the window:
/// - $z + y = u^2$ (some square in the field); and
/// - $z - y$ is not a square.
/// If successful, return a vector of `(z: u64, us: [C::Base; H])` for each window.
fn find_zs_and_us(&self, num_windows: usize) -> Option<Vec<(u64, [C::Base; H])>>;
}
impl<C: CurveAffine> FixedBase<C> for OrchardFixedBase<C> {
fn compute_window_table(&self, num_windows: usize) -> Vec<[C; H]> {
let mut window_table: Vec<[C; H]> = Vec::with_capacity(num_windows);
// Generate window table entries for all windows but the last.
// For these first `num_windows - 1` windows, we compute the multiple [(k+1)*(8^w)]B.
// Here, w ranges from [0..`num_windows - 1`)
for w in 0..(num_windows - 1) {
window_table.push(
(0..H)
.map(|k| {
// scalar = (k+1)*(8^w)
let scalar = C::ScalarExt::from_u64(k as u64 + 1)
* C::ScalarExt::from_u64(H as u64).pow(&[w as u64, 0, 0, 0]);
(self.0 * scalar).to_affine()
})
.collect::<ArrayVec<C, H>>()
.into_inner()
.unwrap(),
);
}
// Generate window table entries for the last window, w = `num_windows - 1`.
// For the last window, we compute [k * (8^w) - sum]B, where sum is defined
// as sum = \sum_{j = 0}^{`num_windows - 2`} 8^j
let sum = (0..(num_windows - 1)).fold(C::ScalarExt::zero(), |acc, w| {
acc + C::ScalarExt::from_u64(H as u64).pow(&[w as u64, 0, 0, 0])
});
window_table.push(
(0..H)
.map(|k| {
// scalar = k * (8^w) - sum, where w = `num_windows - 1`
let scalar = C::ScalarExt::from_u64(k as u64)
* C::ScalarExt::from_u64(H as u64).pow(&[
(num_windows - 1) as u64,
0,
0,
0,
])
- sum;
(self.0 * scalar).to_affine()
})
.collect::<ArrayVec<C, H>>()
.into_inner()
.unwrap(),
);
window_table
}
fn compute_lagrange_coeffs(&self, num_windows: usize) -> Vec<[C::Base; H]> {
// We are interpolating over the 3-bit window, k \in [0..8)
let points: Vec<_> = (0..H).map(|i| C::Base::from_u64(i as u64)).collect();
let window_table = self.compute_window_table(num_windows);
window_table
.iter()
.map(|window_points| {
let x_window_points: Vec<_> = window_points
.iter()
.map(|point| *point.coordinates().unwrap().x())
.collect();
lagrange_interpolate(&points, &x_window_points)
.into_iter()
.collect::<ArrayVec<C::Base, H>>()
.into_inner()
.unwrap()
})
.collect()
}
/// For each window, z is a field element such that for each point (x, y) in the window:
/// - z + y = u^2 (some square in the field); and
/// - z - y is not a square.
/// If successful, return a vector of `(z: u64, us: [C::Base; H])` for each window.
fn find_zs_and_us(&self, num_windows: usize) -> Option<Vec<(u64, [C::Base; H])>> {
// Closure to find z and u's for one window
let find_z_and_us = |window_points: &[C]| {
assert_eq!(H, window_points.len());
let ys: Vec<_> = window_points
.iter()
.map(|point| *point.coordinates().unwrap().y())
.collect();
(0..(1000 * (1 << (2 * H)))).find_map(|z| {
ys.iter()
.map(|&y| {
if (-y + C::Base::from_u64(z)).sqrt().is_none().into() {
(y + C::Base::from_u64(z)).sqrt().into()
} else {
None
}
})
.collect::<Option<ArrayVec<C::Base, H>>>()
.map(|us| (z, us.into_inner().unwrap()))
})
};
let window_table = self.compute_window_table(num_windows);
window_table
.iter()
.map(|window_points| find_z_and_us(window_points))
.collect()
}
}
trait TestFixedBase<C: CurveAffine> {
// Test that Lagrange interpolation coefficients reproduce the correct x-coordinate
// for each fixed-base multiple in each window.
fn test_lagrange_coeffs(&self, num_windows: usize);
// Test that the z-values and u-values satisfy the conditions:
// 1. z + y = u^2,
// 2. z - y is not a square
// for the y-coordinate of each fixed-base multiple in each window.
fn test_z(&self, z: &[u64], u: &[[[u8; 32]; H]], num_windows: usize);
}
impl<C: CurveAffine> TestFixedBase<C> for OrchardFixedBase<C> {
fn test_lagrange_coeffs(&self, num_windows: usize) {
let lagrange_coeffs = self.compute_lagrange_coeffs(num_windows);
// Check first 84 windows, i.e. `k_0, k_1, ..., k_83`
for (idx, coeffs) in lagrange_coeffs[0..(num_windows - 1)].iter().enumerate() {
// Test each three-bit chunk in this window.
for bits in 0..(1 << FIXED_BASE_WINDOW_SIZE) {
{
// Interpolate the x-coordinate using this window's coefficients
let interpolated_x = util::evaluate::<C>(bits, coeffs);
// Compute the actual x-coordinate of the multiple [(k+1)*(8^w)]B.
let point = self.0
* C::Scalar::from_u64(bits as u64 + 1)
* C::Scalar::from_u64(H as u64).pow(&[idx as u64, 0, 0, 0]);
let x = *point.to_affine().coordinates().unwrap().x();
// Check that the interpolated x-coordinate matches the actual one.
assert_eq!(x, interpolated_x);
}
}
}
// Check last window.
for bits in 0..(1 << FIXED_BASE_WINDOW_SIZE) {
// Interpolate the x-coordinate using the last window's coefficients
let interpolated_x = util::evaluate::<C>(bits, &lagrange_coeffs[num_windows - 1]);
// Compute the actual x-coordinate of the multiple [k * (8^84) - offset]B,
// where offset = \sum_{j = 0}^{83} 8^j
let offset = (0..(num_windows - 1)).fold(C::Scalar::zero(), |acc, w| {
acc + C::Scalar::from_u64(H as u64).pow(&[w as u64, 0, 0, 0])
});
let scalar = C::Scalar::from_u64(bits as u64)
* C::Scalar::from_u64(H as u64).pow(&[(num_windows - 1) as u64, 0, 0, 0])
- offset;
let point = self.0 * scalar;
let x = *point.to_affine().coordinates().unwrap().x();
// Check that the interpolated x-coordinate matches the actual one.
assert_eq!(x, interpolated_x);
}
}
fn test_z(&self, z: &[u64], u: &[[[u8; 32]; H]], num_windows: usize) {
let window_table = self.compute_window_table(num_windows);
for ((u, z), window_points) in u.iter().zip(z.iter()).zip(window_table) {
for (u, point) in u.iter().zip(window_points.iter()) {
let y = *point.coordinates().unwrap().y();
let u = C::Base::from_bytes(&u).unwrap();
assert_eq!(C::Base::from_u64(*z) + y, u * u); // allow either square root
assert!(bool::from((C::Base::from_u64(*z) - y).sqrt().is_none()));
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2961
src/constants/nullifier_k.rs Normal file

File diff suppressed because it is too large Load Diff

87
src/constants/util.rs Normal file
View File

@ -0,0 +1,87 @@
use ff::PrimeField;
use halo2::arithmetic::{CurveAffine, FieldExt};
/// Decompose a scalar into `window_num_bits` bits (little-endian)
/// For a window size of `w`, this returns [k_0, ..., k_n] where each `k_i`
/// is a `w`-bit value, and `scalar = k_0 + k_1 * w + k_n * w^n`.
///
/// # Panics
///
/// We are returning a `Vec<u8>` which means the window size is limited to
/// <= 8 bits.
pub fn decompose_scalar_fixed<C: CurveAffine>(
scalar: C::Scalar,
scalar_num_bits: usize,
window_num_bits: usize,
) -> Vec<u8> {
assert!(window_num_bits <= 8);
// Pad bits to multiple of window_num_bits
let padding = (window_num_bits - (scalar_num_bits % window_num_bits)) % window_num_bits;
let bits: Vec<bool> = scalar
.to_le_bits()
.into_iter()
.take(scalar_num_bits)
.chain(std::iter::repeat(false).take(padding))
.collect();
assert_eq!(bits.len(), scalar_num_bits + padding);
bits.chunks_exact(window_num_bits)
.map(|chunk| chunk.iter().rev().fold(0, |acc, b| (acc << 1) + (*b as u8)))
.collect()
}
/// Evaluate y = f(x) given the coefficients of f(x)
pub fn evaluate<C: CurveAffine>(x: u8, coeffs: &[C::Base]) -> C::Base {
let x = C::Base::from_u64(x as u64);
coeffs
.iter()
.rev()
.fold(C::Base::default(), |acc, coeff| acc * x + coeff)
}
#[cfg(test)]
mod tests {
use super::decompose_scalar_fixed;
use ff::PrimeField;
use pasta_curves::{arithmetic::FieldExt, pallas};
use proptest::prelude::*;
use std::convert::TryInto;
use std::iter;
prop_compose! {
fn arb_scalar()(bytes in prop::array::uniform32(0u8..)) -> pallas::Scalar {
// Instead of rejecting out-of-range bytes, let's reduce them.
let mut buf = [0; 64];
buf[..32].copy_from_slice(&bytes);
pallas::Scalar::from_bytes_wide(&buf)
}
}
proptest! {
#[test]
fn test_decompose_scalar_fixed(
scalar in arb_scalar(),
window_num_bits in 1u8..9
) {
// Get decomposition into `window_num_bits` bits
let decomposed = decompose_scalar_fixed::<pallas::Affine>(scalar, pallas::Scalar::NUM_BITS as usize, window_num_bits as usize);
// Flatten bits
let bits = decomposed
.iter()
.flat_map(|window| (0..window_num_bits).map(move |mask| (window & (1 << mask)) != 0));
// Ensure this decomposition contains 256 or fewer set bits.
assert!(!bits.clone().skip(32*8).any(|b| b));
// Pad or truncate bits to 32 bytes
let bits: Vec<bool> = bits.chain(iter::repeat(false)).take(32*8).collect();
let bytes: Vec<u8> = bits.chunks_exact(8).map(|chunk| chunk.iter().rev().fold(0, |acc, b| (acc << 1) + (*b as u8))).collect();
// Check that original scalar is recovered from decomposition
assert_eq!(scalar, pallas::Scalar::from_bytes(&bytes.try_into().unwrap()).unwrap());
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,816 @@
use super::{OrchardFixedBase, ValueCommitV};
use halo2::arithmetic::{CurveAffine, FieldExt};
/// The value commitment is used to check balance between inputs and outputs. The value is
/// placed over this generator.
pub const GENERATOR: ([u8; 32], [u8; 32]) = (
[
103, 67, 249, 58, 110, 189, 167, 42, 140, 124, 90, 43, 127, 163, 4, 254, 50, 178, 155, 79,
112, 106, 168, 247, 66, 15, 61, 142, 122, 89, 112, 47,
],
[
142, 242, 90, 175, 126, 196, 19, 164, 219, 227, 255, 167, 102, 167, 158, 29, 66, 108, 109,
19, 99, 127, 145, 30, 175, 25, 25, 49, 105, 81, 14, 45,
],
);
/// Short signed z-values for GENERATOR
pub const Z_SHORT: [u64; super::NUM_WINDOWS_SHORT] = [
159178, 83716, 37986, 35465, 96663, 56068, 39598, 2197, 184235, 13632, 185448, 4724, 77161,
38274, 68455, 144608, 35437, 202901, 33132, 71081, 80102, 38982,
];
/// Short signed u-values for GENERATOR
pub const U_SHORT: [[[u8; 32]; super::H]; super::NUM_WINDOWS_SHORT] = [
[
[
153, 46, 168, 204, 151, 29, 111, 238, 183, 186, 226, 89, 34, 87, 219, 89, 132, 56, 191,
57, 17, 146, 88, 253, 50, 158, 206, 229, 219, 63, 157, 62,
],
[
78, 151, 207, 212, 243, 203, 197, 42, 77, 122, 201, 13, 11, 147, 105, 68, 18, 165, 40,
131, 115, 238, 90, 114, 7, 21, 183, 40, 95, 192, 16, 17,
],
[
47, 103, 89, 11, 163, 118, 73, 18, 129, 16, 210, 195, 176, 219, 122, 209, 15, 148, 210,
98, 241, 138, 211, 92, 45, 93, 248, 103, 59, 64, 134, 51,
],
[
49, 156, 150, 28, 35, 160, 77, 141, 230, 92, 208, 162, 81, 163, 84, 93, 83, 197, 214,
191, 101, 14, 194, 230, 155, 187, 97, 39, 20, 84, 38, 0,
],
[
20, 212, 159, 245, 212, 130, 77, 52, 26, 153, 202, 130, 18, 156, 170, 78, 71, 79, 44,
107, 191, 39, 56, 30, 220, 9, 30, 100, 186, 207, 88, 29,
],
[
121, 224, 153, 138, 229, 236, 10, 5, 240, 183, 95, 237, 114, 98, 107, 215, 68, 107, 26,
27, 56, 55, 35, 214, 109, 50, 32, 46, 138, 83, 153, 25,
],
[
220, 96, 235, 189, 75, 229, 77, 92, 162, 228, 61, 217, 38, 168, 144, 137, 87, 80, 28,
170, 254, 35, 16, 32, 153, 229, 113, 115, 204, 153, 49, 57,
],
[
18, 51, 85, 218, 253, 170, 105, 92, 210, 210, 74, 3, 124, 134, 94, 48, 17, 192, 92,
251, 225, 123, 121, 145, 217, 177, 220, 13, 189, 61, 120, 51,
],
],
[
[
227, 124, 121, 5, 119, 36, 70, 24, 48, 83, 26, 164, 36, 71, 70, 110, 166, 188, 140,
205, 105, 209, 178, 181, 32, 210, 84, 124, 152, 122, 160, 4,
],
[
174, 222, 65, 201, 15, 152, 12, 5, 206, 215, 218, 169, 51, 203, 1, 206, 108, 7, 119,
48, 145, 96, 175, 161, 90, 189, 175, 54, 171, 129, 92, 11,
],
[
245, 143, 178, 22, 72, 168, 1, 72, 30, 153, 202, 75, 85, 180, 135, 53, 37, 116, 34,
227, 68, 205, 245, 178, 12, 59, 240, 253, 219, 16, 192, 58,
],
[
16, 239, 163, 60, 241, 97, 64, 60, 57, 77, 249, 21, 25, 117, 125, 248, 236, 90, 15, 79,
231, 76, 39, 55, 0, 243, 156, 128, 253, 205, 51, 41,
],
[
22, 233, 138, 209, 178, 129, 253, 55, 253, 206, 81, 96, 0, 177, 160, 160, 187, 182,
241, 96, 75, 255, 180, 221, 85, 155, 134, 254, 35, 80, 98, 48,
],
[
108, 33, 2, 149, 244, 64, 77, 124, 72, 242, 137, 28, 150, 54, 144, 27, 167, 182, 166,
253, 154, 78, 247, 210, 157, 171, 129, 217, 120, 207, 75, 53,
],
[
54, 129, 115, 25, 34, 205, 90, 94, 223, 195, 209, 233, 122, 60, 74, 86, 123, 214, 49,
184, 48, 159, 67, 136, 36, 89, 145, 239, 225, 210, 130, 49,
],
[
208, 44, 184, 206, 64, 200, 3, 22, 50, 24, 254, 31, 205, 229, 202, 249, 170, 137, 84,
112, 236, 128, 107, 222, 210, 132, 192, 29, 237, 64, 158, 33,
],
],
[
[
130, 26, 212, 77, 3, 152, 153, 2, 140, 178, 15, 59, 78, 244, 89, 0, 231, 51, 134, 84,
4, 82, 46, 217, 182, 103, 201, 4, 101, 162, 93, 24,
],
[
49, 9, 84, 214, 21, 239, 175, 146, 156, 227, 151, 148, 235, 14, 37, 143, 1, 246, 46,
170, 164, 132, 233, 128, 23, 205, 37, 50, 224, 107, 28, 14,
],
[
62, 5, 248, 158, 136, 153, 126, 106, 189, 130, 44, 103, 217, 142, 140, 70, 218, 109,
17, 152, 237, 123, 63, 70, 185, 88, 83, 208, 179, 34, 85, 9,
],
[
4, 220, 212, 173, 66, 49, 55, 151, 52, 92, 78, 243, 173, 115, 186, 243, 249, 46, 185,
41, 26, 112, 163, 163, 54, 144, 174, 197, 247, 195, 189, 11,
],
[
187, 33, 40, 98, 41, 250, 164, 229, 249, 118, 119, 252, 34, 121, 27, 248, 183, 5, 93,
47, 255, 22, 99, 211, 180, 219, 99, 167, 115, 235, 228, 18,
],
[
150, 204, 119, 28, 142, 200, 201, 38, 90, 198, 195, 134, 100, 186, 35, 135, 125, 74,
56, 171, 124, 253, 68, 140, 239, 41, 145, 151, 205, 246, 178, 21,
],
[
92, 226, 116, 4, 211, 155, 116, 241, 26, 16, 253, 54, 141, 247, 31, 195, 94, 7, 58,
110, 95, 107, 71, 82, 163, 209, 81, 147, 149, 61, 1, 55,
],
[
199, 195, 138, 44, 202, 34, 152, 144, 252, 186, 240, 187, 244, 23, 26, 131, 250, 19,
185, 184, 68, 81, 3, 144, 85, 83, 15, 197, 63, 171, 226, 51,
],
],
[
[
17, 4, 104, 42, 235, 67, 15, 174, 182, 95, 23, 242, 27, 16, 57, 138, 180, 251, 34, 229,
175, 13, 100, 38, 98, 56, 64, 255, 4, 25, 223, 9,
],
[
120, 156, 69, 234, 42, 249, 66, 154, 17, 134, 93, 118, 77, 193, 108, 194, 1, 111, 201,
97, 56, 111, 44, 62, 50, 55, 201, 84, 75, 217, 228, 32,
],
[
66, 85, 87, 72, 109, 174, 100, 76, 16, 236, 131, 70, 255, 154, 212, 219, 149, 246, 140,
81, 186, 188, 65, 114, 21, 64, 136, 191, 88, 178, 227, 37,
],
[
199, 11, 98, 233, 40, 76, 11, 202, 68, 149, 205, 238, 244, 70, 62, 217, 79, 115, 123,
253, 13, 39, 173, 40, 146, 97, 250, 90, 157, 234, 142, 59,
],
[
158, 190, 3, 192, 131, 141, 230, 62, 210, 233, 113, 128, 116, 83, 204, 48, 118, 188,
106, 164, 207, 52, 131, 218, 176, 178, 172, 83, 190, 248, 203, 43,
],
[
109, 254, 80, 40, 139, 23, 150, 31, 6, 5, 16, 145, 179, 120, 92, 232, 191, 186, 82,
197, 150, 233, 113, 56, 5, 227, 138, 187, 170, 217, 231, 52,
],
[
147, 15, 203, 82, 167, 73, 219, 132, 148, 4, 190, 161, 68, 125, 57, 114, 143, 202, 79,
215, 5, 211, 60, 222, 233, 248, 210, 166, 112, 14, 181, 31,
],
[
95, 44, 184, 188, 177, 131, 106, 227, 134, 185, 12, 23, 220, 220, 99, 31, 129, 233,
167, 17, 183, 162, 57, 32, 240, 201, 247, 42, 107, 62, 210, 33,
],
],
[
[
77, 253, 167, 23, 71, 68, 62, 161, 227, 65, 147, 78, 129, 206, 208, 119, 242, 12, 126,
217, 8, 64, 33, 57, 12, 77, 247, 101, 63, 247, 76, 56,
],
[
247, 217, 213, 0, 240, 169, 14, 208, 209, 107, 3, 113, 213, 84, 55, 121, 39, 38, 92,
195, 126, 39, 95, 19, 169, 226, 238, 75, 118, 171, 78, 0,
],
[
49, 250, 131, 43, 24, 104, 104, 133, 219, 231, 76, 142, 163, 69, 114, 251, 235, 207,
231, 52, 11, 59, 156, 25, 166, 216, 174, 158, 152, 192, 240, 2,
],
[
3, 73, 181, 128, 160, 75, 195, 196, 168, 101, 112, 207, 75, 175, 240, 110, 61, 9, 160,
187, 211, 129, 123, 199, 153, 160, 182, 76, 163, 96, 204, 18,
],
[
255, 45, 150, 115, 143, 93, 60, 226, 254, 164, 93, 6, 184, 26, 111, 174, 218, 175, 106,
149, 43, 229, 124, 223, 8, 59, 175, 10, 162, 73, 223, 24,
],
[
31, 79, 47, 83, 99, 236, 199, 48, 190, 184, 30, 68, 88, 121, 147, 124, 246, 18, 28, 10,
137, 1, 13, 121, 172, 79, 213, 93, 69, 230, 185, 36,
],
[
231, 161, 8, 164, 24, 32, 161, 104, 194, 100, 34, 125, 85, 117, 9, 156, 180, 228, 43,
134, 6, 215, 192, 121, 197, 135, 156, 11, 30, 254, 155, 53,
],
[
233, 26, 0, 17, 192, 101, 179, 154, 40, 76, 102, 176, 25, 156, 148, 7, 11, 51, 6, 248,
30, 124, 151, 39, 43, 58, 45, 56, 209, 190, 157, 35,
],
],
[
[
106, 68, 250, 74, 120, 174, 206, 236, 170, 168, 66, 56, 76, 179, 81, 21, 62, 240, 168,
123, 232, 134, 163, 155, 129, 114, 33, 41, 37, 203, 85, 7,
],
[
200, 243, 177, 92, 234, 192, 223, 156, 194, 225, 114, 2, 206, 71, 95, 111, 23, 210, 67,
194, 250, 61, 182, 216, 111, 250, 220, 198, 179, 49, 146, 34,
],
[
126, 28, 101, 44, 29, 211, 53, 230, 99, 67, 141, 52, 206, 211, 95, 45, 185, 194, 1, 27,
210, 110, 230, 3, 240, 124, 166, 27, 4, 181, 9, 63,
],
[
148, 47, 48, 248, 130, 150, 62, 70, 152, 52, 252, 194, 49, 43, 225, 196, 186, 216, 140,
67, 11, 100, 96, 161, 130, 217, 187, 216, 137, 183, 1, 8,
],
[
194, 203, 116, 188, 172, 186, 63, 160, 76, 78, 14, 93, 42, 68, 203, 76, 121, 150, 195,
128, 22, 27, 11, 153, 56, 70, 194, 66, 9, 151, 34, 16,
],
[
91, 14, 43, 45, 236, 194, 81, 185, 209, 54, 139, 49, 225, 153, 193, 88, 30, 225, 97,
20, 36, 206, 124, 136, 222, 204, 86, 186, 66, 89, 225, 26,
],
[
109, 226, 156, 117, 89, 202, 163, 238, 48, 253, 145, 86, 124, 31, 52, 237, 184, 247,
204, 129, 138, 160, 12, 228, 4, 176, 195, 65, 153, 196, 68, 50,
],
[
19, 135, 6, 142, 64, 78, 165, 253, 217, 155, 153, 41, 145, 248, 98, 122, 63, 157, 59,
170, 195, 100, 143, 83, 152, 181, 181, 120, 8, 144, 154, 1,
],
],
[
[
106, 126, 53, 197, 57, 109, 74, 130, 226, 176, 100, 39, 206, 139, 109, 236, 160, 137,
86, 230, 232, 240, 54, 243, 204, 219, 77, 157, 204, 231, 111, 36,
],
[
226, 55, 121, 73, 104, 77, 129, 202, 168, 123, 192, 163, 28, 9, 195, 37, 116, 207, 125,
198, 203, 244, 121, 236, 232, 91, 168, 14, 142, 241, 250, 60,
],
[
222, 86, 183, 37, 132, 107, 210, 125, 127, 46, 94, 81, 18, 91, 72, 160, 16, 193, 239,
114, 238, 186, 186, 203, 96, 169, 87, 155, 108, 36, 97, 6,
],
[
110, 110, 99, 98, 167, 78, 75, 128, 33, 138, 18, 19, 194, 192, 219, 184, 74, 196, 82,
115, 241, 102, 30, 197, 199, 194, 154, 120, 49, 10, 95, 37,
],
[
212, 206, 154, 98, 20, 33, 185, 182, 138, 207, 65, 197, 246, 19, 132, 52, 173, 186, 42,
243, 88, 20, 51, 11, 206, 25, 216, 48, 162, 138, 124, 13,
],
[
32, 161, 64, 72, 1, 32, 243, 175, 251, 37, 86, 248, 136, 187, 181, 55, 39, 255, 98,
228, 189, 235, 194, 2, 228, 39, 92, 104, 245, 17, 117, 7,
],
[
207, 205, 116, 251, 54, 21, 8, 82, 173, 45, 205, 38, 245, 155, 16, 56, 198, 232, 173,
88, 97, 22, 234, 26, 139, 206, 108, 254, 123, 87, 181, 26,
],
[
38, 147, 223, 169, 68, 76, 49, 169, 137, 141, 72, 63, 166, 88, 34, 220, 163, 91, 167,
251, 29, 160, 254, 199, 205, 74, 158, 105, 252, 182, 158, 21,
],
],
[
[
80, 212, 229, 122, 178, 246, 252, 158, 36, 72, 150, 94, 148, 186, 85, 230, 199, 137,
172, 37, 63, 109, 220, 54, 95, 11, 10, 193, 208, 223, 49, 62,
],
[
189, 222, 8, 252, 190, 238, 142, 250, 125, 255, 46, 11, 111, 167, 161, 95, 166, 213,
250, 67, 181, 26, 148, 21, 146, 253, 190, 125, 117, 248, 70, 29,
],
[
194, 36, 228, 204, 211, 157, 88, 125, 121, 194, 226, 198, 206, 214, 198, 248, 57, 24,
28, 125, 252, 114, 46, 255, 69, 85, 221, 119, 146, 92, 31, 27,
],
[
95, 162, 248, 234, 208, 229, 136, 182, 8, 63, 218, 209, 7, 28, 203, 245, 147, 30, 14,
204, 227, 198, 61, 14, 215, 149, 160, 32, 146, 36, 126, 16,
],
[
126, 195, 159, 66, 184, 207, 152, 70, 49, 131, 6, 95, 216, 136, 255, 17, 60, 12, 68,
204, 163, 99, 196, 88, 220, 176, 175, 55, 116, 77, 40, 5,
],
[
99, 64, 77, 7, 247, 175, 27, 149, 130, 207, 130, 207, 27, 52, 10, 136, 225, 106, 192,
253, 68, 114, 207, 62, 185, 114, 103, 44, 218, 165, 152, 44,
],
[
149, 134, 178, 63, 251, 236, 111, 9, 228, 145, 19, 82, 145, 179, 130, 252, 194, 128, 4,
197, 23, 78, 53, 233, 113, 210, 138, 3, 74, 243, 75, 54,
],
[
255, 141, 71, 29, 12, 174, 6, 74, 168, 248, 132, 218, 221, 211, 123, 112, 147, 25, 79,
26, 142, 80, 82, 73, 121, 196, 136, 238, 174, 192, 252, 53,
],
],
[
[
17, 202, 87, 54, 219, 198, 233, 183, 192, 167, 70, 106, 246, 217, 202, 14, 164, 147,
29, 189, 238, 131, 28, 210, 28, 233, 187, 1, 20, 95, 28, 33,
],
[
168, 63, 171, 45, 83, 4, 202, 196, 171, 64, 167, 178, 160, 214, 149, 33, 118, 209, 130,
169, 17, 4, 28, 5, 36, 114, 226, 130, 174, 14, 39, 2,
],
[
107, 118, 45, 61, 198, 20, 156, 210, 238, 106, 45, 192, 184, 2, 138, 178, 48, 4, 229,
99, 186, 229, 138, 219, 38, 249, 85, 216, 32, 135, 46, 28,
],
[
32, 225, 192, 38, 53, 107, 221, 198, 147, 190, 171, 83, 41, 244, 26, 2, 207, 184, 61,
241, 53, 142, 126, 121, 8, 23, 116, 230, 154, 67, 169, 4,
],
[
203, 188, 146, 157, 208, 20, 27, 107, 237, 56, 122, 96, 81, 240, 205, 5, 80, 250, 5,
22, 145, 108, 14, 215, 16, 186, 40, 0, 75, 188, 66, 35,
],
[
133, 132, 221, 169, 128, 214, 246, 220, 209, 152, 149, 251, 52, 100, 56, 187, 27, 101,
38, 72, 46, 77, 185, 14, 253, 6, 205, 55, 171, 222, 12, 35,
],
[
149, 171, 108, 161, 232, 203, 112, 176, 23, 11, 4, 28, 35, 197, 90, 77, 251, 14, 49, 7,
111, 46, 70, 251, 239, 198, 123, 30, 91, 45, 190, 62,
],
[
1, 138, 134, 124, 193, 231, 58, 48, 93, 215, 224, 34, 229, 186, 63, 123, 20, 29, 7,
216, 64, 235, 206, 168, 137, 101, 197, 145, 161, 86, 127, 40,
],
],
[
[
5, 129, 208, 74, 135, 91, 10, 243, 31, 197, 67, 212, 198, 55, 245, 119, 115, 164, 115,
180, 43, 240, 8, 153, 75, 116, 148, 231, 43, 201, 5, 19,
],
[
211, 241, 132, 151, 202, 132, 40, 117, 214, 144, 142, 114, 236, 112, 10, 4, 36, 112,
187, 110, 74, 58, 95, 248, 87, 103, 131, 170, 11, 66, 255, 28,
],
[
196, 216, 22, 89, 209, 155, 195, 237, 36, 71, 157, 24, 117, 91, 102, 252, 101, 255, 79,
212, 95, 59, 15, 96, 185, 248, 83, 103, 8, 9, 0, 1,
],
[
112, 24, 254, 77, 67, 246, 3, 198, 255, 83, 119, 40, 121, 57, 66, 247, 82, 3, 50, 139,
253, 167, 11, 163, 194, 254, 227, 58, 101, 191, 17, 27,
],
[
83, 37, 71, 248, 142, 50, 244, 40, 122, 194, 76, 69, 5, 224, 224, 253, 102, 185, 37,
216, 123, 194, 83, 202, 164, 26, 120, 69, 4, 254, 53, 35,
],
[
102, 209, 65, 202, 32, 154, 57, 246, 102, 49, 216, 155, 46, 70, 216, 36, 231, 136, 234,
43, 186, 139, 107, 56, 198, 137, 109, 188, 182, 5, 186, 44,
],
[
92, 67, 196, 191, 134, 144, 22, 92, 155, 84, 154, 91, 152, 203, 73, 44, 241, 130, 48,
13, 131, 21, 81, 11, 193, 29, 160, 248, 12, 237, 89, 13,
],
[
224, 213, 123, 250, 119, 38, 253, 41, 101, 211, 51, 53, 227, 252, 30, 148, 19, 180,
140, 71, 179, 5, 181, 69, 196, 8, 92, 43, 120, 145, 54, 52,
],
],
[
[
97, 176, 133, 117, 14, 106, 235, 82, 96, 105, 166, 142, 37, 48, 135, 52, 161, 113, 8,
87, 2, 26, 166, 156, 68, 239, 17, 242, 80, 200, 57, 18,
],
[
134, 86, 222, 149, 100, 74, 103, 52, 24, 190, 116, 148, 163, 145, 218, 159, 229, 42,
198, 203, 19, 108, 165, 5, 31, 48, 12, 11, 124, 4, 118, 1,
],
[
108, 132, 32, 131, 165, 23, 140, 40, 68, 3, 58, 175, 73, 192, 163, 229, 27, 102, 250,
11, 219, 210, 184, 182, 196, 66, 3, 145, 105, 176, 107, 24,
],
[
5, 115, 97, 133, 217, 251, 226, 160, 238, 161, 182, 81, 189, 67, 203, 82, 188, 239, 12,
29, 250, 251, 16, 159, 120, 131, 96, 195, 77, 6, 223, 21,
],
[
253, 255, 134, 37, 149, 71, 138, 247, 209, 153, 94, 101, 75, 226, 150, 65, 5, 182, 237,
206, 115, 57, 251, 49, 46, 169, 231, 160, 242, 165, 192, 47,
],
[
180, 228, 150, 39, 165, 166, 112, 144, 165, 33, 96, 19, 157, 14, 117, 106, 109, 249,
19, 246, 75, 123, 128, 130, 102, 72, 88, 234, 233, 88, 179, 25,
],
[
237, 124, 236, 122, 215, 145, 238, 202, 95, 40, 77, 0, 171, 142, 150, 124, 45, 13, 121,
54, 235, 72, 126, 40, 122, 60, 56, 226, 39, 126, 108, 30,
],
[
213, 60, 110, 70, 142, 244, 74, 101, 149, 230, 144, 245, 147, 160, 212, 228, 145, 45,
75, 172, 185, 18, 175, 156, 165, 47, 67, 20, 218, 254, 100, 60,
],
],
[
[
188, 73, 176, 13, 112, 29, 179, 188, 248, 239, 147, 149, 101, 35, 162, 70, 14, 173, 69,
222, 162, 137, 183, 122, 249, 47, 22, 162, 191, 108, 60, 6,
],
[
208, 151, 12, 84, 84, 37, 232, 61, 224, 192, 135, 214, 197, 23, 250, 130, 73, 218, 75,
80, 245, 244, 93, 196, 38, 81, 85, 252, 45, 90, 115, 28,
],
[
83, 136, 7, 156, 53, 41, 144, 19, 39, 207, 74, 219, 202, 30, 35, 213, 83, 80, 105, 69,
222, 179, 247, 12, 243, 13, 21, 200, 163, 124, 226, 0,
],
[
112, 73, 8, 180, 210, 107, 238, 30, 162, 126, 190, 10, 140, 65, 234, 9, 43, 164, 18,
50, 125, 130, 21, 142, 132, 63, 86, 22, 228, 56, 109, 33,
],
[
145, 217, 254, 30, 44, 166, 2, 12, 40, 58, 196, 159, 250, 138, 240, 255, 215, 242, 207,
121, 191, 230, 111, 26, 43, 77, 129, 5, 179, 154, 153, 34,
],
[
79, 3, 179, 228, 85, 136, 134, 130, 195, 35, 185, 12, 235, 5, 239, 161, 140, 42, 77,
85, 141, 193, 174, 81, 90, 138, 94, 190, 111, 17, 5, 50,
],
[
122, 231, 131, 177, 128, 13, 32, 195, 176, 45, 202, 20, 9, 30, 88, 54, 234, 239, 97,
198, 218, 175, 181, 166, 60, 156, 64, 28, 119, 96, 76, 2,
],
[
228, 67, 105, 12, 196, 88, 251, 253, 148, 19, 77, 81, 26, 146, 204, 184, 28, 25, 186,
250, 191, 129, 240, 53, 216, 249, 253, 77, 95, 46, 193, 55,
],
],
[
[
55, 175, 132, 23, 78, 4, 204, 40, 120, 57, 164, 73, 198, 103, 47, 149, 99, 4, 38, 242,
0, 81, 126, 169, 149, 137, 158, 153, 146, 201, 18, 10,
],
[
250, 168, 64, 134, 214, 43, 196, 128, 107, 20, 201, 151, 246, 94, 2, 70, 38, 179, 196,
184, 253, 132, 103, 191, 212, 175, 9, 227, 32, 128, 35, 15,
],
[
198, 248, 41, 177, 212, 81, 59, 161, 108, 117, 1, 57, 33, 90, 202, 248, 81, 209, 195,
244, 241, 109, 13, 47, 167, 215, 221, 6, 71, 239, 81, 23,
],
[
71, 60, 59, 59, 78, 191, 165, 195, 64, 216, 193, 236, 234, 12, 81, 137, 180, 10, 229,
141, 41, 158, 193, 184, 120, 31, 208, 123, 219, 129, 146, 16,
],
[
225, 31, 201, 225, 137, 96, 157, 189, 155, 223, 145, 90, 195, 103, 235, 205, 176, 45,
157, 233, 111, 211, 148, 94, 10, 206, 231, 113, 6, 254, 132, 52,
],
[
249, 246, 89, 126, 12, 162, 60, 59, 250, 194, 10, 115, 135, 250, 215, 208, 191, 39,
228, 36, 65, 88, 82, 156, 180, 246, 123, 165, 28, 204, 220, 7,
],
[
113, 211, 247, 224, 36, 4, 150, 189, 56, 129, 7, 221, 193, 75, 144, 32, 223, 79, 125,
219, 220, 52, 24, 214, 127, 105, 16, 62, 10, 124, 197, 53,
],
[
81, 227, 222, 204, 188, 10, 217, 12, 19, 183, 217, 53, 76, 100, 140, 56, 240, 12, 220,
62, 54, 106, 203, 8, 103, 210, 122, 55, 255, 137, 40, 63,
],
],
[
[
239, 48, 2, 229, 96, 175, 219, 41, 217, 242, 28, 190, 34, 196, 72, 68, 150, 66, 190,
179, 94, 64, 116, 27, 177, 167, 17, 238, 92, 45, 33, 25,
],
[
77, 141, 99, 93, 205, 139, 98, 11, 51, 45, 174, 82, 200, 76, 198, 145, 253, 107, 39,
243, 153, 86, 115, 230, 177, 253, 46, 105, 53, 169, 73, 6,
],
[
18, 48, 98, 150, 38, 45, 159, 212, 24, 15, 147, 41, 88, 108, 76, 51, 107, 99, 33, 147,
107, 53, 26, 166, 220, 209, 250, 231, 50, 244, 194, 53,
],
[
230, 158, 81, 25, 61, 74, 254, 10, 174, 17, 204, 122, 101, 191, 154, 75, 136, 190, 149,
9, 96, 96, 222, 13, 141, 166, 206, 241, 213, 218, 251, 48,
],
[
54, 0, 153, 54, 134, 31, 9, 108, 108, 76, 49, 5, 204, 63, 176, 198, 225, 114, 120, 252,
32, 234, 75, 149, 101, 185, 143, 248, 110, 96, 202, 33,
],
[
118, 151, 86, 228, 34, 243, 147, 103, 189, 159, 79, 88, 212, 125, 61, 44, 153, 127, 77,
214, 165, 102, 94, 60, 239, 216, 100, 204, 116, 109, 116, 39,
],
[
141, 237, 72, 24, 254, 183, 169, 175, 58, 57, 118, 122, 197, 131, 79, 3, 156, 171, 252,
40, 103, 153, 98, 200, 232, 173, 110, 192, 204, 123, 29, 9,
],
[
50, 65, 139, 37, 241, 184, 123, 38, 245, 228, 51, 156, 65, 68, 177, 78, 145, 90, 47, 5,
106, 79, 57, 135, 33, 65, 251, 180, 27, 42, 247, 30,
],
],
[
[
224, 172, 235, 60, 255, 127, 17, 161, 21, 0, 114, 209, 104, 13, 158, 90, 107, 157, 138,
97, 84, 226, 243, 169, 59, 113, 38, 128, 204, 39, 11, 44,
],
[
4, 31, 70, 85, 44, 250, 159, 59, 94, 242, 229, 24, 55, 90, 218, 132, 195, 109, 9, 124,
123, 161, 152, 40, 228, 248, 79, 82, 176, 201, 25, 39,
],
[
23, 219, 49, 229, 54, 209, 219, 42, 113, 116, 35, 187, 45, 49, 3, 29, 46, 103, 127,
179, 243, 122, 149, 98, 90, 165, 231, 179, 166, 226, 72, 7,
],
[
147, 148, 183, 208, 30, 213, 19, 148, 46, 99, 222, 36, 141, 160, 33, 125, 167, 114, 33,
196, 144, 221, 48, 237, 19, 152, 60, 51, 98, 252, 106, 60,
],
[
124, 133, 88, 120, 245, 245, 33, 217, 219, 61, 238, 3, 52, 13, 122, 98, 148, 227, 208,
135, 117, 214, 221, 77, 36, 140, 12, 171, 8, 170, 101, 39,
],
[
244, 144, 139, 109, 81, 224, 175, 121, 133, 150, 106, 126, 158, 228, 176, 252, 122,
249, 142, 130, 159, 85, 221, 209, 221, 85, 46, 240, 51, 109, 56, 59,
],
[
129, 195, 233, 117, 252, 210, 196, 104, 45, 150, 110, 92, 104, 64, 79, 65, 27, 175, 17,
0, 252, 118, 85, 24, 194, 39, 114, 120, 112, 25, 108, 15,
],
[
131, 77, 116, 55, 232, 22, 109, 37, 22, 183, 229, 85, 209, 183, 171, 160, 242, 52, 10,
37, 247, 13, 42, 115, 228, 119, 218, 124, 120, 186, 231, 34,
],
],
[
[
101, 213, 255, 130, 121, 109, 64, 193, 97, 26, 239, 215, 84, 92, 224, 190, 237, 31, 22,
142, 78, 133, 94, 215, 123, 255, 19, 251, 84, 147, 122, 33,
],
[
200, 154, 112, 158, 61, 87, 112, 63, 37, 48, 68, 51, 11, 98, 245, 10, 132, 68, 202,
157, 112, 231, 183, 184, 75, 137, 60, 128, 165, 129, 46, 25,
],
[
106, 39, 142, 0, 134, 133, 71, 20, 186, 182, 222, 200, 34, 165, 94, 241, 63, 166, 176,
124, 247, 61, 255, 69, 172, 114, 68, 58, 163, 20, 232, 7,
],
[
3, 99, 112, 133, 145, 205, 167, 185, 1, 115, 82, 45, 11, 182, 221, 41, 10, 129, 2, 159,
198, 19, 167, 245, 27, 144, 247, 217, 71, 87, 209, 6,
],
[
44, 127, 76, 114, 193, 159, 227, 227, 147, 86, 62, 247, 220, 165, 195, 68, 24, 122,
142, 110, 5, 116, 184, 117, 156, 12, 108, 44, 6, 98, 66, 15,
],
[
148, 177, 230, 118, 113, 10, 253, 235, 130, 15, 137, 108, 93, 21, 228, 62, 66, 130, 11,
190, 140, 82, 143, 170, 224, 54, 146, 33, 150, 165, 30, 47,
],
[
91, 186, 47, 20, 63, 142, 194, 162, 29, 172, 52, 103, 153, 27, 14, 121, 35, 203, 66,
48, 252, 188, 95, 100, 56, 90, 127, 129, 224, 141, 196, 34,
],
[
85, 9, 146, 0, 253, 158, 36, 77, 184, 116, 220, 186, 93, 239, 104, 253, 186, 125, 82,
28, 221, 119, 19, 175, 214, 244, 240, 39, 202, 192, 82, 9,
],
],
[
[
173, 63, 103, 33, 120, 177, 22, 128, 225, 55, 71, 36, 61, 235, 240, 38, 210, 164, 28,
95, 75, 112, 158, 210, 239, 72, 140, 62, 123, 221, 202, 33,
],
[
33, 92, 119, 167, 130, 76, 79, 163, 120, 226, 183, 233, 70, 244, 221, 12, 132, 147,
123, 139, 73, 156, 36, 199, 152, 225, 108, 129, 122, 165, 16, 28,
],
[
131, 77, 125, 131, 67, 53, 52, 138, 169, 96, 89, 252, 224, 218, 155, 97, 16, 177, 100,
143, 7, 119, 57, 8, 178, 245, 106, 193, 153, 27, 150, 35,
],
[
139, 90, 1, 77, 207, 145, 119, 77, 124, 230, 54, 142, 216, 164, 92, 177, 242, 96, 19,
240, 125, 28, 190, 216, 109, 22, 163, 31, 35, 38, 93, 60,
],
[
107, 195, 155, 17, 230, 231, 212, 221, 95, 117, 221, 197, 137, 16, 111, 52, 179, 42,
126, 144, 205, 96, 220, 134, 6, 49, 163, 192, 53, 70, 109, 42,
],
[
122, 3, 60, 119, 85, 172, 227, 142, 55, 9, 27, 6, 13, 40, 119, 179, 26, 39, 35, 105,
155, 154, 183, 71, 39, 119, 47, 91, 34, 3, 98, 34,
],
[
129, 52, 165, 103, 105, 220, 137, 167, 98, 250, 64, 158, 190, 40, 180, 55, 133, 186,
116, 75, 146, 221, 28, 191, 1, 78, 151, 231, 194, 4, 220, 21,
],
[
18, 210, 152, 250, 122, 65, 54, 240, 159, 203, 220, 252, 251, 103, 53, 161, 207, 163,
11, 237, 249, 206, 65, 131, 207, 228, 8, 119, 19, 65, 222, 52,
],
],
[
[
122, 90, 71, 168, 233, 221, 224, 182, 249, 138, 42, 153, 231, 27, 6, 64, 245, 179, 53,
97, 248, 210, 74, 238, 28, 19, 66, 248, 195, 237, 64, 36,
],
[
90, 115, 165, 218, 163, 197, 210, 143, 213, 125, 1, 77, 74, 165, 200, 244, 80, 39, 20,
247, 86, 120, 109, 109, 93, 7, 209, 199, 109, 12, 144, 46,
],
[
231, 44, 48, 128, 109, 202, 114, 192, 218, 67, 233, 141, 64, 251, 104, 41, 58, 212, 60,
65, 93, 58, 34, 149, 128, 90, 30, 197, 191, 244, 8, 37,
],
[
56, 47, 18, 80, 195, 143, 175, 35, 183, 225, 201, 236, 138, 29, 26, 229, 194, 202, 13,
43, 71, 188, 3, 204, 12, 15, 218, 207, 15, 83, 219, 39,
],
[
50, 71, 182, 171, 33, 129, 211, 168, 40, 85, 193, 218, 165, 54, 220, 203, 164, 124, 8,
37, 19, 210, 8, 253, 120, 158, 239, 239, 28, 195, 253, 37,
],
[
245, 191, 155, 103, 118, 221, 209, 204, 89, 48, 249, 160, 180, 1, 114, 3, 254, 220, 94,
244, 221, 122, 224, 55, 184, 106, 99, 11, 236, 89, 211, 38,
],
[
182, 208, 168, 152, 15, 192, 45, 31, 93, 181, 13, 203, 128, 82, 126, 145, 129, 220, 19,
252, 188, 247, 49, 216, 218, 198, 178, 70, 180, 209, 175, 22,
],
[
72, 71, 200, 22, 21, 120, 50, 111, 112, 195, 141, 79, 49, 52, 98, 8, 37, 130, 142, 13,
78, 197, 15, 92, 203, 50, 108, 82, 109, 254, 158, 12,
],
],
[
[
56, 162, 66, 19, 204, 252, 161, 42, 1, 87, 96, 119, 9, 220, 167, 193, 119, 175, 24,
202, 152, 248, 221, 14, 87, 98, 153, 15, 255, 242, 112, 47,
],
[
208, 87, 78, 186, 184, 128, 38, 190, 131, 156, 221, 119, 87, 12, 144, 4, 240, 77, 118,
209, 74, 131, 37, 155, 247, 155, 206, 167, 80, 71, 127, 18,
],
[
190, 54, 229, 228, 15, 167, 185, 240, 161, 238, 216, 88, 210, 31, 242, 20, 81, 147, 48,
54, 38, 226, 251, 64, 69, 196, 67, 166, 242, 34, 118, 39,
],
[
58, 171, 187, 174, 13, 247, 253, 15, 102, 171, 48, 63, 136, 157, 55, 28, 117, 130, 104,
23, 145, 203, 155, 105, 121, 249, 115, 106, 88, 114, 86, 11,
],
[
105, 30, 100, 75, 20, 206, 29, 147, 150, 37, 48, 216, 33, 147, 61, 193, 82, 230, 205,
122, 142, 65, 148, 102, 47, 185, 182, 147, 185, 31, 29, 54,
],
[
158, 245, 169, 236, 26, 185, 17, 174, 156, 69, 81, 196, 60, 109, 99, 91, 19, 208, 93,
58, 9, 109, 228, 186, 109, 127, 171, 156, 229, 215, 195, 59,
],
[
23, 42, 4, 183, 91, 177, 2, 172, 168, 182, 158, 185, 157, 118, 199, 184, 237, 203, 60,
170, 35, 121, 162, 7, 130, 171, 121, 207, 32, 2, 227, 62,
],
[
0, 139, 174, 217, 13, 116, 28, 230, 238, 117, 190, 91, 86, 105, 38, 231, 147, 100, 233,
187, 70, 128, 111, 82, 184, 113, 154, 136, 59, 27, 21, 10,
],
],
[
[
30, 110, 207, 178, 188, 230, 1, 85, 120, 157, 171, 131, 200, 18, 180, 82, 176, 44, 151,
2, 5, 144, 142, 16, 247, 40, 95, 88, 90, 249, 199, 1,
],
[
214, 131, 68, 196, 131, 169, 22, 250, 29, 101, 142, 26, 106, 96, 18, 190, 18, 15, 19,
59, 203, 203, 119, 251, 61, 221, 198, 116, 24, 178, 61, 42,
],
[
101, 161, 133, 103, 0, 112, 204, 255, 98, 240, 20, 161, 242, 253, 216, 204, 83, 96, 93,
228, 77, 76, 63, 70, 116, 156, 69, 253, 121, 189, 2, 36,
],
[
156, 83, 226, 206, 4, 35, 12, 137, 209, 181, 109, 81, 194, 119, 188, 216, 30, 233, 135,
220, 213, 40, 74, 152, 49, 14, 0, 3, 223, 41, 238, 54,
],
[
47, 25, 110, 4, 111, 57, 200, 91, 168, 73, 47, 175, 189, 60, 49, 243, 128, 11, 63, 17,
151, 123, 80, 140, 139, 202, 93, 104, 190, 32, 67, 54,
],
[
90, 100, 132, 107, 167, 162, 164, 62, 239, 68, 20, 223, 157, 1, 90, 95, 248, 82, 65,
61, 241, 63, 238, 10, 2, 160, 230, 104, 101, 197, 60, 52,
],
[
41, 144, 80, 156, 134, 224, 6, 48, 188, 57, 30, 205, 84, 135, 190, 75, 213, 94, 16, 72,
11, 96, 41, 117, 75, 60, 62, 133, 29, 133, 105, 15,
],
[
219, 66, 247, 117, 3, 137, 38, 43, 131, 177, 137, 150, 9, 65, 160, 206, 235, 121, 121,
245, 205, 233, 229, 78, 72, 200, 171, 149, 240, 64, 184, 5,
],
],
[
[
7, 198, 172, 18, 241, 109, 130, 105, 143, 167, 90, 133, 249, 6, 215, 112, 194, 30, 97,
44, 91, 247, 120, 188, 218, 32, 76, 202, 5, 223, 164, 4,
],
[
49, 50, 95, 247, 20, 72, 200, 36, 210, 155, 239, 220, 84, 130, 194, 226, 151, 248, 209,
68, 128, 244, 193, 15, 27, 81, 176, 201, 101, 60, 167, 43,
],
[
39, 100, 26, 150, 252, 191, 240, 208, 79, 173, 40, 9, 198, 39, 182, 201, 156, 22, 31,
9, 195, 86, 231, 92, 228, 35, 85, 8, 16, 99, 102, 18,
],
[
80, 52, 146, 205, 17, 188, 48, 239, 194, 36, 97, 172, 242, 7, 88, 233, 157, 175, 68,
91, 99, 177, 28, 196, 195, 159, 187, 145, 3, 138, 123, 10,
],
[
217, 120, 36, 243, 226, 20, 7, 61, 148, 103, 42, 165, 42, 109, 63, 122, 115, 83, 236,
216, 209, 229, 21, 106, 89, 236, 204, 255, 251, 168, 217, 9,
],
[
84, 103, 125, 109, 193, 110, 218, 6, 50, 52, 216, 219, 170, 111, 102, 97, 185, 70, 193,
64, 95, 75, 100, 62, 15, 54, 0, 50, 15, 47, 22, 58,
],
[
70, 91, 82, 46, 116, 140, 86, 194, 235, 94, 141, 109, 41, 221, 143, 196, 146, 27, 70,
16, 44, 231, 206, 155, 52, 237, 6, 194, 123, 85, 44, 35,
],
[
201, 150, 157, 236, 223, 8, 24, 174, 234, 170, 95, 168, 197, 113, 149, 174, 214, 252,
140, 146, 11, 57, 114, 99, 140, 169, 88, 37, 112, 90, 75, 25,
],
],
[
[
58, 90, 180, 85, 181, 149, 44, 248, 114, 241, 224, 4, 48, 238, 195, 30, 129, 226, 202,
65, 245, 160, 165, 130, 250, 49, 123, 218, 33, 244, 44, 34,
],
[
160, 56, 55, 244, 243, 171, 30, 93, 225, 5, 4, 144, 83, 142, 11, 27, 225, 3, 170, 216,
121, 38, 126, 229, 81, 76, 161, 158, 185, 218, 133, 49,
],
[
53, 123, 61, 76, 166, 244, 231, 194, 129, 37, 29, 86, 103, 9, 130, 80, 237, 93, 240,
48, 202, 168, 204, 190, 255, 154, 183, 136, 100, 126, 31, 18,
],
[
178, 173, 151, 199, 225, 179, 74, 122, 27, 148, 1, 134, 85, 89, 5, 47, 167, 203, 15,
185, 114, 139, 164, 150, 132, 239, 108, 96, 184, 135, 195, 22,
],
[
151, 21, 1, 41, 129, 198, 151, 27, 7, 1, 192, 77, 166, 9, 204, 133, 171, 204, 63, 5,
76, 85, 181, 61, 239, 42, 141, 225, 52, 194, 154, 38,
],
[
173, 139, 63, 185, 110, 98, 51, 235, 76, 116, 23, 105, 144, 72, 101, 39, 125, 137, 99,
196, 163, 36, 68, 201, 46, 120, 5, 195, 63, 195, 91, 61,
],
[
190, 38, 194, 50, 43, 10, 159, 131, 143, 165, 63, 240, 241, 131, 64, 63, 192, 49, 45,
105, 136, 224, 77, 108, 57, 31, 235, 202, 104, 149, 222, 62,
],
[
244, 99, 92, 132, 254, 61, 45, 229, 74, 234, 250, 148, 115, 76, 81, 144, 175, 184, 158,
217, 69, 231, 117, 65, 9, 60, 50, 12, 0, 138, 32, 28,
],
],
];
pub fn generator<C: CurveAffine>() -> ValueCommitV<C> {
ValueCommitV(OrchardFixedBase::<C>::new(
C::from_xy(
C::Base::from_bytes(&GENERATOR.0).unwrap(),
C::Base::from_bytes(&GENERATOR.1).unwrap(),
)
.unwrap(),
))
}
#[cfg(test)]
mod tests {
use super::super::{TestFixedBase, NUM_WINDOWS_SHORT, VALUE_COMMITMENT_PERSONALIZATION};
use super::*;
use group::Curve;
use halo2::{
arithmetic::{CurveAffine, CurveExt, FieldExt},
pasta::pallas,
};
#[test]
fn generator() {
let hasher = pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION);
let point = hasher(b"v");
let coords = point.to_affine().coordinates().unwrap();
assert_eq!(*coords.x(), pallas::Base::from_bytes(&GENERATOR.0).unwrap());
assert_eq!(*coords.y(), pallas::Base::from_bytes(&GENERATOR.1).unwrap());
}
#[test]
fn lagrange_coeffs_short() {
let base = super::generator::<pallas::Affine>();
base.0.test_lagrange_coeffs(NUM_WINDOWS_SHORT);
}
#[test]
fn z_short() {
let base = super::generator::<pallas::Affine>();
base.0.test_z(&Z_SHORT, &U_SHORT, NUM_WINDOWS_SHORT);
}
}

View File

@ -10,6 +10,7 @@ mod addition;
use self::addition::IncompletePoint;
mod constants;
mod sinsemilla_s;
pub use constants::*;
fn lebs2ip_k(bits: &[bool]) -> u32 {

View File

@ -1,4 +1,6 @@
//! Sinsemilla generators
use group::Curve;
use halo2::arithmetic::{CurveAffine, CurveExt};
/// Number of bits of each message piece in $\mathsf{SinsemillaHashToPoint}$
pub const K: usize = 10;
@ -12,7 +14,122 @@ pub const C: usize = 253;
/// SWU hash-to-curve personalization for Sinsemilla $Q$ generators.
pub const Q_PERSONALIZATION: &str = "z.cash:SinsemillaQ";
/// Generator used in SinsemillaHashToPoint for note commitment
pub const Q_NOTE_COMMITMENT_M_GENERATOR: ([u8; 32], [u8; 32]) = (
[
93, 116, 168, 64, 9, 186, 14, 50, 42, 221, 70, 253, 90, 15, 150, 197, 93, 237, 176, 121,
180, 242, 159, 247, 13, 205, 251, 86, 160, 7, 128, 23,
],
[
99, 172, 73, 115, 90, 10, 39, 135, 158, 94, 219, 129, 136, 18, 34, 136, 44, 201, 244, 110,
217, 194, 190, 78, 131, 112, 198, 138, 147, 88, 160, 50,
],
);
/// Generator used in SinsemillaHashToPoint for IVK commitment
pub const Q_COMMIT_IVK_M_GENERATOR: ([u8; 32], [u8; 32]) = (
[
242, 130, 15, 121, 146, 47, 203, 107, 50, 162, 40, 81, 36, 204, 27, 66, 250, 65, 162, 90,
184, 129, 204, 125, 17, 200, 169, 74, 241, 12, 188, 5,
],
[
190, 222, 173, 207, 206, 229, 90, 190, 241, 165, 109, 201, 29, 53, 196, 70, 75, 5, 222, 32,
70, 7, 89, 239, 230, 190, 26, 212, 246, 76, 1, 27,
],
);
/// Generator used in SinsemillaHashToPoint for Merkle collision-resistant hash
pub const Q_MERKLE_CRH: ([u8; 32], [u8; 32]) = (
[
160, 198, 41, 127, 249, 199, 185, 248, 112, 16, 141, 192, 85, 185, 190, 201, 153, 14, 137,
239, 90, 54, 15, 160, 185, 24, 168, 99, 150, 210, 22, 22,
],
[
98, 234, 242, 37, 206, 174, 233, 134, 150, 21, 116, 5, 234, 150, 28, 226, 121, 89, 163, 79,
62, 242, 196, 45, 153, 32, 175, 227, 163, 66, 134, 53,
],
);
// Sinsemilla S generators
/// SWU hash-to-curve personalization for Sinsemilla $S$ generators.
pub const S_PERSONALIZATION: &str = "z.cash:SinsemillaS";
/// Creates the Sinsemilla S generators used in each round of the Sinsemilla hash
pub fn sinsemilla_s_generators<C: CurveAffine>() -> impl Iterator<Item = (C::Base, C::Base)> {
let hasher = C::CurveExt::hash_to_curve(S_PERSONALIZATION);
(0..(1u32 << K)).map(move |j| {
let point = hasher(&j.to_le_bytes()).to_affine().coordinates().unwrap();
(*point.x(), *point.y())
})
}
#[cfg(test)]
mod tests {
use super::super::{CommitDomain, HashDomain};
use super::*;
use crate::constants::{
COMMIT_IVK_PERSONALIZATION, MERKLE_CRH_PERSONALIZATION, NOTE_COMMITMENT_PERSONALIZATION,
};
use group::Curve;
use halo2::arithmetic::FieldExt;
use halo2::pasta::pallas;
#[test]
fn sinsemilla_s() {
use super::super::sinsemilla_s::SINSEMILLA_S;
let sinsemilla_s: Vec<_> = sinsemilla_s_generators::<pallas::Affine>().collect();
assert_eq!(sinsemilla_s.len(), SINSEMILLA_S.len());
for (expected, actual) in sinsemilla_s.iter().zip(&SINSEMILLA_S[..]) {
assert_eq!(expected, actual);
}
}
#[test]
fn q_note_commitment_m() {
let domain = CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION);
let point = domain.M.Q;
let coords = point.to_affine().coordinates().unwrap();
assert_eq!(
*coords.x(),
pallas::Base::from_bytes(&Q_NOTE_COMMITMENT_M_GENERATOR.0).unwrap()
);
assert_eq!(
*coords.y(),
pallas::Base::from_bytes(&Q_NOTE_COMMITMENT_M_GENERATOR.1).unwrap()
);
}
#[test]
fn q_commit_ivk_m() {
let domain = CommitDomain::new(COMMIT_IVK_PERSONALIZATION);
let point = domain.M.Q;
let coords = point.to_affine().coordinates().unwrap();
assert_eq!(
*coords.x(),
pallas::Base::from_bytes(&Q_COMMIT_IVK_M_GENERATOR.0).unwrap()
);
assert_eq!(
*coords.y(),
pallas::Base::from_bytes(&Q_COMMIT_IVK_M_GENERATOR.1).unwrap()
);
}
#[test]
fn q_merkle_crh() {
let domain = HashDomain::new(MERKLE_CRH_PERSONALIZATION);
let point = domain.Q;
let coords = point.to_affine().coordinates().unwrap();
assert_eq!(
*coords.x(),
pallas::Base::from_bytes(&Q_MERKLE_CRH.0).unwrap()
);
assert_eq!(
*coords.y(),
pallas::Base::from_bytes(&Q_MERKLE_CRH.1).unwrap()
);
}
}

File diff suppressed because it is too large Load Diff