Merge pull request #135 from zcash/patch-ncc

Partial fixes from NCC draft report
This commit is contained in:
Kris Nuttycombe 2021-07-22 15:25:05 -06:00 committed by GitHub
commit b86967bc57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 26 additions and 7 deletions

View File

@ -161,6 +161,11 @@ fn compute_lagrange_coeffs<C: CurveAffine>(base: C, num_windows: usize) -> Vec<[
/// - $z + y = u^2$ (some square in the field); and /// - $z + y = u^2$ (some square in the field); and
/// - $z - y$ is not a square. /// - $z - y$ is not a square.
/// If successful, return a vector of `(z: u64, us: [C::Base; H])` for each window. /// If successful, return a vector of `(z: u64, us: [C::Base; H])` for each window.
///
/// This function was used to generate the `z`s and `u`s for the Orchard fixed
/// bases. The outputs of this function have been stored as constants, and it
/// is not called anywhere in this codebase. However, we keep this function here
/// as a utility for those who wish to use it with different parameters.
fn find_zs_and_us<C: CurveAffine>(base: C, num_windows: usize) -> Option<Vec<(u64, [C::Base; H])>> { fn find_zs_and_us<C: CurveAffine>(base: C, num_windows: usize) -> Option<Vec<(u64, [C::Base; H])>> {
// Closure to find z and u's for one window // Closure to find z and u's for one window
let find_z_and_us = |window_points: &[C]| { let find_z_and_us = |window_points: &[C]| {

View File

@ -1,4 +1,4 @@
use ff::PrimeFieldBits; use ff::{Field, PrimeFieldBits};
use halo2::arithmetic::{CurveAffine, FieldExt}; use halo2::arithmetic::{CurveAffine, FieldExt};
/// Decompose a word `alpha` into `window_num_bits` bits (little-endian) /// Decompose a word `alpha` into `window_num_bits` bits (little-endian)
@ -37,7 +37,9 @@ pub fn evaluate<C: CurveAffine>(x: u8, coeffs: &[C::Base]) -> C::Base {
coeffs coeffs
.iter() .iter()
.rev() .rev()
.fold(C::Base::default(), |acc, coeff| acc * x + coeff) .cloned()
.reduce(|acc, coeff| acc * x + coeff)
.unwrap_or_else(C::Base::zero)
} }
/// Takes in an FnMut closure and returns a constant-length array with elements of /// Takes in an FnMut closure and returns a constant-length array with elements of

View File

@ -5,7 +5,12 @@ use ff::PrimeFieldBits;
use pasta_curves::{arithmetic::FieldExt, pallas}; use pasta_curves::{arithmetic::FieldExt, pallas};
use subtle::{ConstantTimeEq, CtOption}; use subtle::{ConstantTimeEq, CtOption};
use crate::{constants::L_ORCHARD_BASE, primitives::sinsemilla, spec::extract_p, value::NoteValue}; use crate::{
constants::{L_ORCHARD_BASE, NOTE_COMMITMENT_PERSONALIZATION},
primitives::sinsemilla,
spec::extract_p,
value::NoteValue,
};
pub(super) struct NoteCommitTrapdoor(pub(super) pallas::Scalar); pub(super) struct NoteCommitTrapdoor(pub(super) pallas::Scalar);
@ -27,7 +32,7 @@ impl NoteCommitment {
psi: pallas::Base, psi: pallas::Base,
rcm: NoteCommitTrapdoor, rcm: NoteCommitTrapdoor,
) -> CtOption<Self> { ) -> CtOption<Self> {
let domain = sinsemilla::CommitDomain::new("z.cash:Orchard-NoteCommit"); let domain = sinsemilla::CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION);
domain domain
.commit( .commit(
iter::empty() iter::empty()

View File

@ -127,6 +127,10 @@ impl HashDomain {
/// $\mathsf{SinsemillaHash}$ from [§ 5.4.1.9][concretesinsemillahash]. /// $\mathsf{SinsemillaHash}$ from [§ 5.4.1.9][concretesinsemillahash].
/// ///
/// [concretesinsemillahash]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillahash /// [concretesinsemillahash]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillahash
///
/// # Panics
///
/// This panics if the message length is greater than [`K`] * [`C`]
pub(crate) fn hash(&self, msg: impl Iterator<Item = bool>) -> CtOption<pallas::Base> { pub(crate) fn hash(&self, msg: impl Iterator<Item = bool>) -> CtOption<pallas::Base> {
extract_p_bottom(self.hash_to_point(msg)) extract_p_bottom(self.hash_to_point(msg))
} }

View File

@ -11,7 +11,10 @@ use pasta_curves::pallas;
use subtle::{ConditionallySelectable, CtOption}; use subtle::{ConditionallySelectable, CtOption};
use crate::{ use crate::{
constants::{util::gen_const_array, L_ORCHARD_BASE}, constants::{
util::gen_const_array, COMMIT_IVK_PERSONALIZATION, KEY_DIVERSIFICATION_PERSONALIZATION,
L_ORCHARD_BASE,
},
primitives::{poseidon, sinsemilla}, primitives::{poseidon, sinsemilla},
}; };
@ -171,7 +174,7 @@ pub(crate) fn commit_ivk(
) -> CtOption<NonZeroPallasBase> { ) -> CtOption<NonZeroPallasBase> {
// We rely on the API contract that to_le_bits() returns at least PrimeField::NUM_BITS // We rely on the API contract that to_le_bits() returns at least PrimeField::NUM_BITS
// bits, which is equal to L_ORCHARD_BASE. // bits, which is equal to L_ORCHARD_BASE.
let domain = sinsemilla::CommitDomain::new("z.cash:Orchard-CommitIvk"); let domain = sinsemilla::CommitDomain::new(COMMIT_IVK_PERSONALIZATION);
domain domain
.short_commit( .short_commit(
iter::empty() iter::empty()
@ -192,7 +195,7 @@ pub(crate) fn commit_ivk(
/// ///
/// [concretediversifyhash]: https://zips.z.cash/protocol/nu5.pdf#concretediversifyhash /// [concretediversifyhash]: https://zips.z.cash/protocol/nu5.pdf#concretediversifyhash
pub(crate) fn diversify_hash(d: &[u8; 11]) -> NonIdentityPallasPoint { pub(crate) fn diversify_hash(d: &[u8; 11]) -> NonIdentityPallasPoint {
let hasher = pallas::Point::hash_to_curve("z.cash:Orchard-gd"); let hasher = pallas::Point::hash_to_curve(KEY_DIVERSIFICATION_PERSONALIZATION);
let pk_d = hasher(d); let pk_d = hasher(d);
// If the identity occurs, we replace it with a different fixed point. // If the identity occurs, we replace it with a different fixed point.
// TODO: Replace the unwrap_or_else with a cached fixed point. // TODO: Replace the unwrap_or_else with a cached fixed point.