mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
crypto/constants: Update with latest Orchard constants.
This commit is contained in:
@@ -2,10 +2,19 @@ pub mod fixed_bases;
|
||||
pub mod sinsemilla;
|
||||
pub mod util;
|
||||
|
||||
pub use fixed_bases::OrchardFixedBases;
|
||||
pub use fixed_bases::{NullifierK, OrchardFixedBases, OrchardFixedBasesFull, ValueCommitV, H};
|
||||
|
||||
pub const DRK_SCHNORR_DOMAIN: &[u8] = b"DarkFi_Schnorr";
|
||||
|
||||
pub const MERKLE_DEPTH_ORCHARD: usize = 32;
|
||||
|
||||
pub const L_ORCHARD_MERKLE: usize = 255;
|
||||
|
||||
/// $\ell^\mathsf{Orchard}_\mathsf{base}$
|
||||
pub(crate) const L_ORCHARD_BASE: usize = 255;
|
||||
|
||||
/// $\ell^\mathsf{Orchard}_\mathsf{scalar}$
|
||||
pub(crate) const L_ORCHARD_SCALAR: usize = 255;
|
||||
|
||||
/// $\ell_\mathsf{value}$
|
||||
pub(crate) const L_VALUE: usize = 64;
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
use arrayvec::ArrayVec;
|
||||
//! Orchard fixed bases.
|
||||
use super::{L_ORCHARD_SCALAR, L_VALUE};
|
||||
use halo2_gadgets::ecc::{
|
||||
chip::{compute_lagrange_coeffs, NUM_WINDOWS, NUM_WINDOWS_SHORT},
|
||||
FixedPoints, H,
|
||||
};
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, Field, FieldExt},
|
||||
group::Curve,
|
||||
pallas,
|
||||
chip::{BaseFieldElem, FixedPoint, FullScalar, ShortScalar},
|
||||
FixedPoints,
|
||||
};
|
||||
|
||||
use pasta_curves::pallas;
|
||||
|
||||
pub mod commit_ivk_r;
|
||||
pub mod note_commit_r;
|
||||
pub mod nullifier_k;
|
||||
@@ -16,14 +14,18 @@ pub mod spend_auth_g;
|
||||
pub mod value_commit_r;
|
||||
pub mod value_commit_v;
|
||||
|
||||
/// 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 value commitment generator
|
||||
pub const VALUE_COMMITMENT_PERSONALIZATION: &str = "z.cash:Orchard-cv";
|
||||
|
||||
/// SWU hash-to-curve value for the value commitment generator
|
||||
pub const VALUE_COMMITMENT_R_BYTES: [u8; 1] = *b"r";
|
||||
pub const VALUE_COMMITMENT_V_BYTES: [u8; 1] = *b"v";
|
||||
|
||||
/// SWU hash-to-curve value for the value commitment generator
|
||||
pub const VALUE_COMMITMENT_V_BYTES: [u8; 1] = *b"v";
|
||||
pub const VALUE_COMMITMENT_R_BYTES: [u8; 1] = *b"r";
|
||||
|
||||
/// SWU hash-to-curve personalization for the note commitment generator
|
||||
pub const NOTE_COMMITMENT_PERSONALIZATION: &str = "z.cash:Orchard-NoteCommit";
|
||||
@@ -31,184 +33,129 @@ 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 spending key base point and
|
||||
/// the nullifier base point K^Orchard
|
||||
pub const ORCHARD_PERSONALIZATION: &str = "z.cash:Orchard";
|
||||
|
||||
/// 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 =
|
||||
(L_ORCHARD_SCALAR + 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;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
// A sum type for both full-width and short bases. This enables us to use the
|
||||
// shared functionality of full-width and short fixed-base scalar multiplication.
|
||||
pub enum OrchardFixedBases {
|
||||
CommitIvkR,
|
||||
NoteCommitR,
|
||||
ValueCommitR,
|
||||
SpendAuthG,
|
||||
Full(OrchardFixedBasesFull),
|
||||
NullifierK,
|
||||
ValueCommitV,
|
||||
}
|
||||
|
||||
impl From<OrchardFixedBasesFull> for OrchardFixedBases {
|
||||
fn from(full_width_base: OrchardFixedBasesFull) -> Self {
|
||||
Self::Full(full_width_base)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ValueCommitV> for OrchardFixedBases {
|
||||
fn from(_value_commit_v: ValueCommitV) -> Self {
|
||||
Self::ValueCommitV
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NullifierK> for OrchardFixedBases {
|
||||
fn from(_nullifier_k: NullifierK) -> Self {
|
||||
Self::NullifierK
|
||||
}
|
||||
}
|
||||
|
||||
/// The Orchard fixed bases used in scalar mul with full-width scalars.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum OrchardFixedBasesFull {
|
||||
CommitIvkR,
|
||||
NoteCommitR,
|
||||
ValueCommitR,
|
||||
SpendAuthG,
|
||||
}
|
||||
|
||||
/// NullifierK is used in scalar mul with a base field element.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub struct NullifierK;
|
||||
|
||||
/// ValueCommitV is used in scalar mul with a short signed scalar.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub struct ValueCommitV;
|
||||
|
||||
impl FixedPoints<pallas::Affine> for OrchardFixedBases {
|
||||
type FullScalar = OrchardFixedBasesFull;
|
||||
type Base = NullifierK;
|
||||
type ShortScalar = ValueCommitV;
|
||||
}
|
||||
|
||||
impl FixedPoint<pallas::Affine> for OrchardFixedBasesFull {
|
||||
type ScalarKind = FullScalar;
|
||||
|
||||
fn generator(&self) -> pallas::Affine {
|
||||
match self {
|
||||
OrchardFixedBases::CommitIvkR => commit_ivk_r::generator(),
|
||||
OrchardFixedBases::NoteCommitR => note_commit_r::generator(),
|
||||
OrchardFixedBases::ValueCommitR => value_commit_r::generator(),
|
||||
OrchardFixedBases::SpendAuthG => spend_auth_g::generator(),
|
||||
OrchardFixedBases::NullifierK => nullifier_k::generator(),
|
||||
OrchardFixedBases::ValueCommitV => value_commit_v::generator(),
|
||||
Self::CommitIvkR => commit_ivk_r::generator(),
|
||||
Self::NoteCommitR => note_commit_r::generator(),
|
||||
Self::ValueCommitR => value_commit_r::generator(),
|
||||
Self::SpendAuthG => spend_auth_g::generator(),
|
||||
}
|
||||
}
|
||||
|
||||
fn u(&self) -> Vec<[[u8; 32]; H]> {
|
||||
match self {
|
||||
OrchardFixedBases::CommitIvkR => commit_ivk_r::U.to_vec(),
|
||||
OrchardFixedBases::NoteCommitR => note_commit_r::U.to_vec(),
|
||||
OrchardFixedBases::ValueCommitR => value_commit_r::U.to_vec(),
|
||||
OrchardFixedBases::SpendAuthG => spend_auth_g::U.to_vec(),
|
||||
OrchardFixedBases::NullifierK => nullifier_k::U.to_vec(),
|
||||
OrchardFixedBases::ValueCommitV => value_commit_v::U_SHORT.to_vec(),
|
||||
Self::CommitIvkR => commit_ivk_r::U.to_vec(),
|
||||
Self::NoteCommitR => note_commit_r::U.to_vec(),
|
||||
Self::ValueCommitR => value_commit_r::U.to_vec(),
|
||||
Self::SpendAuthG => spend_auth_g::U.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
fn z(&self) -> Vec<u64> {
|
||||
match self {
|
||||
OrchardFixedBases::CommitIvkR => commit_ivk_r::Z.to_vec(),
|
||||
OrchardFixedBases::NoteCommitR => note_commit_r::Z.to_vec(),
|
||||
OrchardFixedBases::ValueCommitR => value_commit_r::Z.to_vec(),
|
||||
OrchardFixedBases::SpendAuthG => spend_auth_g::Z.to_vec(),
|
||||
OrchardFixedBases::NullifierK => nullifier_k::Z.to_vec(),
|
||||
OrchardFixedBases::ValueCommitV => value_commit_v::Z_SHORT.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
fn lagrange_coeffs(&self) -> Vec<[pallas::Base; H]> {
|
||||
match self {
|
||||
OrchardFixedBases::ValueCommitV => {
|
||||
compute_lagrange_coeffs(self.generator(), NUM_WINDOWS_SHORT)
|
||||
}
|
||||
_ => compute_lagrange_coeffs(self.generator(), NUM_WINDOWS),
|
||||
Self::CommitIvkR => commit_ivk_r::Z.to_vec(),
|
||||
Self::NoteCommitR => note_commit_r::Z.to_vec(),
|
||||
Self::ValueCommitR => value_commit_r::Z.to_vec(),
|
||||
Self::SpendAuthG => spend_auth_g::Z.to_vec(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// For each fixed base, we calculate its scalar multiples in three-bit windows.
|
||||
/// Each window will have $2^3 = 8$ points.
|
||||
#[allow(dead_code)]
|
||||
fn compute_window_table<C: CurveAffine>(base: C, num_windows: usize) -> Vec<[C; H]> {
|
||||
let mut window_table: Vec<[C; H]> = Vec::with_capacity(num_windows);
|
||||
impl FixedPoint<pallas::Affine> for NullifierK {
|
||||
type ScalarKind = BaseFieldElem;
|
||||
|
||||
// Generate window table entries for all windows but the last.
|
||||
// For these first `num_windows - 1` windows, we compute the multiple [(k+2)*(2^3)^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+2)*(8^w)
|
||||
let scalar = C::ScalarExt::from_u64(k as u64 + 2) *
|
||||
C::ScalarExt::from_u64(H as u64).pow(&[w as u64, 0, 0, 0]);
|
||||
(base * scalar).to_affine()
|
||||
})
|
||||
.collect::<ArrayVec<C, H>>()
|
||||
.into_inner()
|
||||
.unwrap(),
|
||||
);
|
||||
fn generator(&self) -> pallas::Affine {
|
||||
nullifier_k::generator()
|
||||
}
|
||||
|
||||
// Generate window table entries for the last window, w = `num_windows - 1`.
|
||||
// For the last window, we compute [k * (2^3)^w - sum]B, where sum is defined
|
||||
// as sum = \sum_{j = 0}^{`num_windows - 2`} 2^{3j+1}
|
||||
let sum = (0..(num_windows - 1)).fold(C::ScalarExt::zero(), |acc, j| {
|
||||
acc + C::ScalarExt::from_u64(2).pow(&[
|
||||
FIXED_BASE_WINDOW_SIZE as u64 * j as u64 + 1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
])
|
||||
});
|
||||
window_table.push(
|
||||
(0..H)
|
||||
.map(|k| {
|
||||
// scalar = k * (2^3)^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;
|
||||
(base * scalar).to_affine()
|
||||
})
|
||||
.collect::<ArrayVec<C, H>>()
|
||||
.into_inner()
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
window_table
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
// Test that Lagrange interpolation coefficients reproduce the correct x-coordinate
|
||||
// for each fixed-base multiple in each window.
|
||||
fn test_lagrange_coeffs<C: CurveAffine>(base: C, num_windows: usize) {
|
||||
let lagrange_coeffs = compute_lagrange_coeffs(base, 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 = super::util::evaluate::<C>(bits, coeffs);
|
||||
|
||||
// Compute the actual x-coordinate of the multiple [(k+2)*(8^w)]B.
|
||||
let point = base *
|
||||
C::Scalar::from_u64(bits as u64 + 2) *
|
||||
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);
|
||||
}
|
||||
}
|
||||
fn u(&self) -> Vec<[[u8; 32]; H]> {
|
||||
nullifier_k::U.to_vec()
|
||||
}
|
||||
|
||||
// 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 = super::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} 2^{3j+1}
|
||||
let offset = (0..(num_windows - 1)).fold(C::Scalar::zero(), |acc, w| {
|
||||
acc + C::Scalar::from_u64(2).pow(&[
|
||||
FIXED_BASE_WINDOW_SIZE as u64 * w as u64 + 1,
|
||||
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 = base * 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 z(&self) -> Vec<u64> {
|
||||
nullifier_k::Z.to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
// 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_zs_and_us<C: CurveAffine>(base: C, z: &[u64], u: &[[[u8; 32]; H]], num_windows: usize) {
|
||||
let window_table = compute_window_table(base, num_windows);
|
||||
impl FixedPoint<pallas::Affine> for ValueCommitV {
|
||||
type ScalarKind = ShortScalar;
|
||||
|
||||
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()));
|
||||
}
|
||||
fn generator(&self) -> pallas::Affine {
|
||||
value_commit_v::generator()
|
||||
}
|
||||
|
||||
fn u(&self) -> Vec<[[u8; 32]; H]> {
|
||||
value_commit_v::U_SHORT.to_vec()
|
||||
}
|
||||
|
||||
fn z(&self) -> Vec<u64> {
|
||||
value_commit_v::Z_SHORT.to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, FieldExt},
|
||||
pallas,
|
||||
};
|
||||
use group::ff::PrimeField;
|
||||
use pasta_curves::{arithmetic::CurveAffine, pallas};
|
||||
|
||||
/// Generator used in SinsemillaCommit randomness for IVK commitment
|
||||
pub const GENERATOR: ([u8; 32], [u8; 32]) = (
|
||||
@@ -2922,8 +2920,8 @@ pub const U: [[[u8; 32]; super::H]; super::NUM_WINDOWS] = [
|
||||
|
||||
pub fn generator() -> pallas::Affine {
|
||||
pallas::Affine::from_xy(
|
||||
pallas::Base::from_bytes(&GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_bytes(&GENERATOR.1).unwrap(),
|
||||
pallas::Base::from_repr(GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_repr(GENERATOR.1).unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
@@ -2931,15 +2929,15 @@ pub fn generator() -> pallas::Affine {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
super::{test_lagrange_coeffs, test_zs_and_us, COMMIT_IVK_PERSONALIZATION, NUM_WINDOWS},
|
||||
super::{COMMIT_IVK_PERSONALIZATION, NUM_WINDOWS},
|
||||
*,
|
||||
};
|
||||
use group::Curve;
|
||||
use halo2_gadgets::primitives::sinsemilla::CommitDomain;
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, FieldExt},
|
||||
pallas,
|
||||
use halo2_gadgets::{
|
||||
ecc::chip::constants::{test_lagrange_coeffs, test_zs_and_us},
|
||||
primitives::sinsemilla::CommitDomain,
|
||||
};
|
||||
use pasta_curves::{arithmetic::CurveAffine, pallas};
|
||||
|
||||
#[test]
|
||||
fn generator() {
|
||||
@@ -2947,8 +2945,8 @@ mod tests {
|
||||
let point = domain.R();
|
||||
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());
|
||||
assert_eq!(*coords.x(), pallas::Base::from_repr(GENERATOR.0).unwrap());
|
||||
assert_eq!(*coords.y(), pallas::Base::from_repr(GENERATOR.1).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, FieldExt},
|
||||
pallas,
|
||||
};
|
||||
use group::ff::PrimeField;
|
||||
use pasta_curves::{arithmetic::CurveAffine, pallas};
|
||||
|
||||
/// Generator used in SinsemillaCommit randomness for note commitment
|
||||
pub const GENERATOR: ([u8; 32], [u8; 32]) = (
|
||||
@@ -2922,8 +2920,8 @@ pub const U: [[[u8; 32]; super::H]; super::NUM_WINDOWS] = [
|
||||
|
||||
pub fn generator() -> pallas::Affine {
|
||||
pallas::Affine::from_xy(
|
||||
pallas::Base::from_bytes(&GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_bytes(&GENERATOR.1).unwrap(),
|
||||
pallas::Base::from_repr(GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_repr(GENERATOR.1).unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
@@ -2931,26 +2929,25 @@ pub fn generator() -> pallas::Affine {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
super::{
|
||||
test_lagrange_coeffs, test_zs_and_us, NOTE_COMMITMENT_PERSONALIZATION, NUM_WINDOWS,
|
||||
},
|
||||
super::{NOTE_COMMITMENT_PERSONALIZATION, NUM_WINDOWS},
|
||||
*,
|
||||
};
|
||||
use group::Curve;
|
||||
use halo2_gadgets::primitives::sinsemilla::CommitDomain;
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, FieldExt},
|
||||
pallas,
|
||||
use halo2_gadgets::{
|
||||
ecc::chip::constants::{test_lagrange_coeffs, test_zs_and_us},
|
||||
primitives::sinsemilla::CommitDomain,
|
||||
};
|
||||
|
||||
use group::Curve;
|
||||
use pasta_curves::{arithmetic::CurveAffine, pallas};
|
||||
|
||||
#[test]
|
||||
fn generator() {
|
||||
let domain = CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION);
|
||||
let point = domain.R();
|
||||
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());
|
||||
assert_eq!(*coords.x(), pallas::Base::from_repr(GENERATOR.0).unwrap());
|
||||
assert_eq!(*coords.y(), pallas::Base::from_repr(GENERATOR.1).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, FieldExt},
|
||||
pallas,
|
||||
};
|
||||
use group::ff::PrimeField;
|
||||
use pasta_curves::{arithmetic::CurveAffine, pallas};
|
||||
|
||||
pub const GENERATOR: ([u8; 32], [u8; 32]) = (
|
||||
[
|
||||
@@ -2921,8 +2919,8 @@ pub const U: [[[u8; 32]; super::H]; super::NUM_WINDOWS] = [
|
||||
|
||||
pub fn generator() -> pallas::Affine {
|
||||
pallas::Affine::from_xy(
|
||||
pallas::Base::from_bytes(&GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_bytes(&GENERATOR.1).unwrap(),
|
||||
pallas::Base::from_repr(GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_repr(GENERATOR.1).unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
@@ -2930,14 +2928,12 @@ pub fn generator() -> pallas::Affine {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
super::{test_lagrange_coeffs, test_zs_and_us, NUM_WINDOWS, ORCHARD_PERSONALIZATION},
|
||||
super::{NUM_WINDOWS, ORCHARD_PERSONALIZATION},
|
||||
*,
|
||||
};
|
||||
use group::Curve;
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveExt, FieldExt},
|
||||
pallas,
|
||||
};
|
||||
use halo2_gadgets::ecc::chip::constants::{test_lagrange_coeffs, test_zs_and_us};
|
||||
use pasta_curves::{arithmetic::CurveExt, pallas};
|
||||
|
||||
#[test]
|
||||
fn generator() {
|
||||
@@ -2945,8 +2941,8 @@ mod tests {
|
||||
let point = hasher(b"K");
|
||||
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());
|
||||
assert_eq!(*coords.x(), pallas::Base::from_repr(GENERATOR.0).unwrap());
|
||||
assert_eq!(*coords.y(), pallas::Base::from_repr(GENERATOR.1).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, FieldExt},
|
||||
pallas,
|
||||
};
|
||||
use group::ff::PrimeField;
|
||||
use pasta_curves::{arithmetic::CurveAffine, pallas};
|
||||
|
||||
/// The value commitment is used to check balance between inputs and outputs. The value is
|
||||
/// placed over this generator.
|
||||
@@ -2923,8 +2921,8 @@ pub const U: [[[u8; 32]; super::H]; super::NUM_WINDOWS] = [
|
||||
|
||||
pub fn generator() -> pallas::Affine {
|
||||
pallas::Affine::from_xy(
|
||||
pallas::Base::from_bytes(&GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_bytes(&GENERATOR.1).unwrap(),
|
||||
pallas::Base::from_repr(GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_repr(GENERATOR.1).unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
@@ -2932,12 +2930,13 @@ pub fn generator() -> pallas::Affine {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
super::{test_lagrange_coeffs, test_zs_and_us, NUM_WINDOWS, ORCHARD_PERSONALIZATION},
|
||||
super::{NUM_WINDOWS, ORCHARD_PERSONALIZATION},
|
||||
*,
|
||||
};
|
||||
use group::Curve;
|
||||
use halo2_gadgets::ecc::chip::constants::{test_lagrange_coeffs, test_zs_and_us};
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, CurveExt, FieldExt},
|
||||
arithmetic::{CurveAffine, CurveExt},
|
||||
pallas,
|
||||
};
|
||||
|
||||
@@ -2947,8 +2946,8 @@ mod tests {
|
||||
let point = hasher(b"G");
|
||||
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());
|
||||
assert_eq!(*coords.x(), pallas::Base::from_repr(GENERATOR.0).unwrap());
|
||||
assert_eq!(*coords.y(), pallas::Base::from_repr(GENERATOR.1).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, FieldExt},
|
||||
pallas,
|
||||
};
|
||||
use group::ff::PrimeField;
|
||||
use pasta_curves::{arithmetic::CurveAffine, pallas};
|
||||
|
||||
/// The value commitment is used to check balance between inputs and outputs. The value is
|
||||
/// placed over this generator.
|
||||
@@ -2923,8 +2921,8 @@ pub const U: [[[u8; 32]; super::H]; super::NUM_WINDOWS] = [
|
||||
|
||||
pub fn generator() -> pallas::Affine {
|
||||
pallas::Affine::from_xy(
|
||||
pallas::Base::from_bytes(&GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_bytes(&GENERATOR.1).unwrap(),
|
||||
pallas::Base::from_repr(GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_repr(GENERATOR.1).unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
@@ -2932,14 +2930,13 @@ pub fn generator() -> pallas::Affine {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
super::{
|
||||
test_lagrange_coeffs, test_zs_and_us, NUM_WINDOWS, VALUE_COMMITMENT_PERSONALIZATION,
|
||||
},
|
||||
super::{NUM_WINDOWS, VALUE_COMMITMENT_PERSONALIZATION},
|
||||
*,
|
||||
};
|
||||
use group::Curve;
|
||||
use halo2_gadgets::ecc::chip::constants::{test_lagrange_coeffs, test_zs_and_us};
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, CurveExt, FieldExt},
|
||||
arithmetic::{CurveAffine, CurveExt},
|
||||
pallas,
|
||||
};
|
||||
|
||||
@@ -2949,8 +2946,8 @@ mod tests {
|
||||
let point = hasher(b"r");
|
||||
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());
|
||||
assert_eq!(*coords.x(), pallas::Base::from_repr(GENERATOR.0).unwrap());
|
||||
assert_eq!(*coords.y(), pallas::Base::from_repr(GENERATOR.1).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, FieldExt},
|
||||
pallas,
|
||||
};
|
||||
use group::ff::PrimeField;
|
||||
use pasta_curves::{arithmetic::CurveAffine, pallas};
|
||||
|
||||
/// The value commitment is used to check balance between inputs and outputs. The value is
|
||||
/// placed over this generator.
|
||||
@@ -776,8 +774,8 @@ pub const U_SHORT: [[[u8; 32]; super::H]; super::NUM_WINDOWS_SHORT] = [
|
||||
|
||||
pub fn generator() -> pallas::Affine {
|
||||
pallas::Affine::from_xy(
|
||||
pallas::Base::from_bytes(&GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_bytes(&GENERATOR.1).unwrap(),
|
||||
pallas::Base::from_repr(GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_repr(GENERATOR.1).unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
@@ -785,15 +783,13 @@ pub fn generator() -> pallas::Affine {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
super::{
|
||||
test_lagrange_coeffs, test_zs_and_us, NUM_WINDOWS_SHORT,
|
||||
VALUE_COMMITMENT_PERSONALIZATION,
|
||||
},
|
||||
super::{NUM_WINDOWS_SHORT, VALUE_COMMITMENT_PERSONALIZATION},
|
||||
*,
|
||||
};
|
||||
use group::Curve;
|
||||
use halo2_gadgets::ecc::chip::constants::{test_lagrange_coeffs, test_zs_and_us};
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, CurveExt, FieldExt},
|
||||
arithmetic::{CurveAffine, CurveExt},
|
||||
pallas,
|
||||
};
|
||||
|
||||
@@ -803,18 +799,18 @@ mod tests {
|
||||
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());
|
||||
assert_eq!(*coords.x(), pallas::Base::from_repr(GENERATOR.0).unwrap());
|
||||
assert_eq!(*coords.y(), pallas::Base::from_repr(GENERATOR.1).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lagrange_coeffs_short() {
|
||||
fn lagrange_coeffs() {
|
||||
let base = super::generator();
|
||||
test_lagrange_coeffs(base, NUM_WINDOWS_SHORT);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn z_short() {
|
||||
fn z() {
|
||||
let base = super::generator();
|
||||
test_zs_and_us(base, &Z_SHORT, &U_SHORT, NUM_WINDOWS_SHORT);
|
||||
}
|
||||
|
||||
257
src/crypto/constants/load.rs
Normal file
257
src/crypto/constants/load.rs
Normal file
@@ -0,0 +1,257 @@
|
||||
use std::convert::TryInto;
|
||||
|
||||
use crate::constants::{self, compute_lagrange_coeffs, H, NUM_WINDOWS, NUM_WINDOWS_SHORT};
|
||||
use group::ff::PrimeField;
|
||||
use pasta_curves::pallas;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum OrchardFixedBasesFull {
|
||||
CommitIvkR,
|
||||
NoteCommitR,
|
||||
ValueCommitR,
|
||||
SpendAuthG,
|
||||
}
|
||||
|
||||
impl OrchardFixedBasesFull {
|
||||
pub fn generator(&self) -> pallas::Affine {
|
||||
match self {
|
||||
OrchardFixedBasesFull::CommitIvkR => super::commit_ivk_r::generator(),
|
||||
OrchardFixedBasesFull::NoteCommitR => super::note_commit_r::generator(),
|
||||
OrchardFixedBasesFull::ValueCommitR => super::value_commit_r::generator(),
|
||||
OrchardFixedBasesFull::SpendAuthG => super::spend_auth_g::generator(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u(&self) -> U {
|
||||
match self {
|
||||
OrchardFixedBasesFull::CommitIvkR => super::commit_ivk_r::U.into(),
|
||||
OrchardFixedBasesFull::NoteCommitR => super::note_commit_r::U.into(),
|
||||
OrchardFixedBasesFull::ValueCommitR => super::value_commit_r::U.into(),
|
||||
OrchardFixedBasesFull::SpendAuthG => super::spend_auth_g::U.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A fixed base to be used in scalar multiplication with a full-width scalar.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct OrchardFixedBase {
|
||||
pub generator: pallas::Affine,
|
||||
pub lagrange_coeffs: LagrangeCoeffs,
|
||||
pub z: Z,
|
||||
pub u: U,
|
||||
}
|
||||
|
||||
impl From<OrchardFixedBasesFull> for OrchardFixedBase {
|
||||
fn from(base: OrchardFixedBasesFull) -> Self {
|
||||
let (generator, z, u) = match base {
|
||||
OrchardFixedBasesFull::CommitIvkR => (
|
||||
super::commit_ivk_r::generator(),
|
||||
super::commit_ivk_r::Z.into(),
|
||||
super::commit_ivk_r::U.into(),
|
||||
),
|
||||
OrchardFixedBasesFull::NoteCommitR => (
|
||||
super::note_commit_r::generator(),
|
||||
super::note_commit_r::Z.into(),
|
||||
super::note_commit_r::U.into(),
|
||||
),
|
||||
OrchardFixedBasesFull::ValueCommitR => (
|
||||
super::value_commit_r::generator(),
|
||||
super::value_commit_r::Z.into(),
|
||||
super::value_commit_r::U.into(),
|
||||
),
|
||||
OrchardFixedBasesFull::SpendAuthG => (
|
||||
super::spend_auth_g::generator(),
|
||||
super::spend_auth_g::Z.into(),
|
||||
super::spend_auth_g::U.into(),
|
||||
),
|
||||
};
|
||||
|
||||
Self {
|
||||
generator,
|
||||
lagrange_coeffs: compute_lagrange_coeffs(generator, NUM_WINDOWS).into(),
|
||||
z,
|
||||
u,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A fixed base to be used in scalar multiplication with a base field element.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct ValueCommitV {
|
||||
pub generator: pallas::Affine,
|
||||
pub lagrange_coeffs_short: LagrangeCoeffsShort,
|
||||
pub z_short: ZShort,
|
||||
pub u_short: UShort,
|
||||
}
|
||||
|
||||
impl ValueCommitV {
|
||||
pub fn get() -> Self {
|
||||
let generator = super::value_commit_v::generator();
|
||||
Self {
|
||||
generator,
|
||||
lagrange_coeffs_short: compute_lagrange_coeffs(generator, NUM_WINDOWS_SHORT).into(),
|
||||
z_short: super::value_commit_v::Z_SHORT.into(),
|
||||
u_short: super::value_commit_v::U_SHORT.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A fixed base to be used in scalar multiplication with a short signed exponent.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub struct NullifierK;
|
||||
|
||||
impl From<NullifierK> for OrchardFixedBase {
|
||||
fn from(_nullifier_k: NullifierK) -> Self {
|
||||
let (generator, z, u) = (
|
||||
super::nullifier_k::generator(),
|
||||
super::nullifier_k::Z.into(),
|
||||
super::nullifier_k::U.into(),
|
||||
);
|
||||
Self {
|
||||
generator,
|
||||
lagrange_coeffs: compute_lagrange_coeffs(generator, NUM_WINDOWS).into(),
|
||||
z,
|
||||
u,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NullifierK {
|
||||
pub fn generator(&self) -> pallas::Affine {
|
||||
super::nullifier_k::generator()
|
||||
}
|
||||
|
||||
pub fn u(&self) -> U {
|
||||
super::nullifier_k::U.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
// 8 coefficients per window
|
||||
pub struct WindowLagrangeCoeffs(pub Box<[pallas::Base; H]>);
|
||||
|
||||
impl From<&[pallas::Base; H]> for WindowLagrangeCoeffs {
|
||||
fn from(array: &[pallas::Base; H]) -> Self {
|
||||
Self(Box::new(*array))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
// 85 windows per base (with the exception of ValueCommitV)
|
||||
pub struct LagrangeCoeffs(pub Box<[WindowLagrangeCoeffs; constants::NUM_WINDOWS]>);
|
||||
|
||||
impl From<Vec<WindowLagrangeCoeffs>> for LagrangeCoeffs {
|
||||
fn from(windows: Vec<WindowLagrangeCoeffs>) -> Self {
|
||||
Self(windows.into_boxed_slice().try_into().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<[pallas::Base; H]>> for LagrangeCoeffs {
|
||||
fn from(arrays: Vec<[pallas::Base; H]>) -> Self {
|
||||
let windows: Vec<WindowLagrangeCoeffs> = arrays.iter().map(|array| array.into()).collect();
|
||||
windows.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
// 22 windows for ValueCommitV
|
||||
pub struct LagrangeCoeffsShort(pub Box<[WindowLagrangeCoeffs; NUM_WINDOWS_SHORT]>);
|
||||
|
||||
impl From<Vec<WindowLagrangeCoeffs>> for LagrangeCoeffsShort {
|
||||
fn from(windows: Vec<WindowLagrangeCoeffs>) -> Self {
|
||||
Self(windows.into_boxed_slice().try_into().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<[pallas::Base; H]>> for LagrangeCoeffsShort {
|
||||
fn from(arrays: Vec<[pallas::Base; H]>) -> Self {
|
||||
let windows: Vec<WindowLagrangeCoeffs> = arrays.iter().map(|array| array.into()).collect();
|
||||
windows.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
// 85 Z's per base (with the exception of ValueCommitV)
|
||||
pub struct Z(pub Box<[pallas::Base; NUM_WINDOWS]>);
|
||||
|
||||
impl From<[u64; NUM_WINDOWS]> for Z {
|
||||
fn from(zs: [u64; NUM_WINDOWS]) -> Self {
|
||||
Self(
|
||||
zs.iter()
|
||||
.map(|z| pallas::Base::from(*z))
|
||||
.collect::<Vec<_>>()
|
||||
.into_boxed_slice()
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
// 22 Z's for ValueCommitV
|
||||
pub struct ZShort(pub Box<[pallas::Base; NUM_WINDOWS_SHORT]>);
|
||||
|
||||
impl From<[u64; NUM_WINDOWS_SHORT]> for ZShort {
|
||||
fn from(zs: [u64; NUM_WINDOWS_SHORT]) -> Self {
|
||||
Self(
|
||||
zs.iter()
|
||||
.map(|z| pallas::Base::from(*z))
|
||||
.collect::<Vec<_>>()
|
||||
.into_boxed_slice()
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
// 8 u's per window
|
||||
pub struct WindowUs(pub Box<[pallas::Base; H]>);
|
||||
|
||||
impl From<&[[u8; 32]; H]> for WindowUs {
|
||||
fn from(window_us: &[[u8; 32]; H]) -> Self {
|
||||
Self(
|
||||
window_us
|
||||
.iter()
|
||||
.map(|u| pallas::Base::from_repr(*u).unwrap())
|
||||
.collect::<Vec<_>>()
|
||||
.into_boxed_slice()
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
// 85 windows per base (with the exception of ValueCommitV)
|
||||
pub struct U(pub Box<[WindowUs; NUM_WINDOWS]>);
|
||||
|
||||
impl From<Vec<WindowUs>> for U {
|
||||
fn from(windows: Vec<WindowUs>) -> Self {
|
||||
Self(windows.into_boxed_slice().try_into().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[[[u8; 32]; H]; NUM_WINDOWS]> for U {
|
||||
fn from(window_us: [[[u8; 32]; H]; NUM_WINDOWS]) -> Self {
|
||||
let windows: Vec<WindowUs> = window_us.iter().map(|us| us.into()).collect();
|
||||
windows.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
// 22 windows for ValueCommitV
|
||||
pub struct UShort(pub Box<[WindowUs; NUM_WINDOWS_SHORT]>);
|
||||
|
||||
impl From<Vec<WindowUs>> for UShort {
|
||||
fn from(windows: Vec<WindowUs>) -> Self {
|
||||
Self(windows.into_boxed_slice().try_into().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[[[u8; 32]; H]; NUM_WINDOWS_SHORT]> for UShort {
|
||||
fn from(window_us: [[[u8; 32]; H]; NUM_WINDOWS_SHORT]) -> Self {
|
||||
let windows: Vec<WindowUs> = window_us.iter().map(|us| us.into()).collect();
|
||||
windows.into()
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,10 @@
|
||||
//! Sinsemilla generators
|
||||
use super::OrchardFixedBases;
|
||||
//use crate::spec::i2lebsp;
|
||||
|
||||
use super::{OrchardFixedBases, OrchardFixedBasesFull};
|
||||
use crate::crypto::util::i2lebsp;
|
||||
use halo2_gadgets::sinsemilla::{CommitDomains, HashDomains};
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, FieldExt},
|
||||
pallas,
|
||||
};
|
||||
|
||||
use group::ff::PrimeField;
|
||||
use pasta_curves::{arithmetic::CurveAffine, pallas};
|
||||
|
||||
/// Number of bits of each message piece in $\mathsf{SinsemillaHashToPoint}$
|
||||
pub const K: usize = 10;
|
||||
@@ -21,19 +19,12 @@ pub const INV_TWO_POW_K: [u8; 32] = [
|
||||
/// of Pallas.
|
||||
pub const C: usize = 253;
|
||||
|
||||
/// $\ell^\mathsf{Orchard}_\mathsf{Merkle}$
|
||||
pub(crate) const L_ORCHARD_MERKLE: usize = 255;
|
||||
|
||||
/// SWU hash-to-curve personalization for the Merkle CRH generator
|
||||
pub const MERKLE_CRH_PERSONALIZATION: &str = "z.cash:Orchard-MerkleCRH";
|
||||
|
||||
// Sinsemilla Q generators
|
||||
|
||||
/// SWU hash-to-curve personalization for Sinsemilla $Q$ generators.
|
||||
pub const Q_PERSONALIZATION: &str = "z.cash:SinsemillaQ";
|
||||
|
||||
// Sinsemilla S generators
|
||||
|
||||
/// SWU hash-to-curve personalization for Sinsemilla $S$ generators.
|
||||
pub const S_PERSONALIZATION: &str = "z.cash:SinsemillaS";
|
||||
|
||||
/// Generator used in SinsemillaHashToPoint for note commitment
|
||||
pub const Q_NOTE_COMMITMENT_M_GENERATOR: ([u8; 32], [u8; 32]) = (
|
||||
[
|
||||
@@ -70,20 +61,14 @@ pub const Q_MERKLE_CRH: ([u8; 32], [u8; 32]) = (
|
||||
],
|
||||
);
|
||||
|
||||
pub fn i2lebsp<const NUM_BITS: usize>(int: u64) -> [bool; NUM_BITS] {
|
||||
assert!(NUM_BITS <= 64);
|
||||
super::util::gen_const_array(|mask: usize| (int & (1 << mask)) != 0)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn lebs2ip_k(bits: &[bool]) -> u32 {
|
||||
pub(crate) fn lebs2ip_k(bits: &[bool]) -> u32 {
|
||||
assert!(bits.len() == K);
|
||||
bits.iter().enumerate().fold(0u32, |acc, (i, b)| acc + if *b { 1 << i } else { 0 })
|
||||
}
|
||||
|
||||
/// The sequence of K bits in little-endian order representing an integer
|
||||
/// up to `2^K` - 1.
|
||||
pub fn i2lebsp_k(int: usize) -> [bool; K] {
|
||||
pub(crate) fn i2lebsp_k(int: usize) -> [bool; K] {
|
||||
assert!(int < (1 << K));
|
||||
i2lebsp(int as u64)
|
||||
}
|
||||
@@ -100,18 +85,18 @@ impl HashDomains<pallas::Affine> for OrchardHashDomains {
|
||||
fn Q(&self) -> pallas::Affine {
|
||||
match self {
|
||||
OrchardHashDomains::CommitIvk => pallas::Affine::from_xy(
|
||||
pallas::Base::from_bytes(&Q_COMMIT_IVK_M_GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_bytes(&Q_COMMIT_IVK_M_GENERATOR.1).unwrap(),
|
||||
pallas::Base::from_repr(Q_COMMIT_IVK_M_GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_repr(Q_COMMIT_IVK_M_GENERATOR.1).unwrap(),
|
||||
)
|
||||
.unwrap(),
|
||||
OrchardHashDomains::NoteCommit => pallas::Affine::from_xy(
|
||||
pallas::Base::from_bytes(&Q_NOTE_COMMITMENT_M_GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_bytes(&Q_NOTE_COMMITMENT_M_GENERATOR.1).unwrap(),
|
||||
pallas::Base::from_repr(Q_NOTE_COMMITMENT_M_GENERATOR.0).unwrap(),
|
||||
pallas::Base::from_repr(Q_NOTE_COMMITMENT_M_GENERATOR.1).unwrap(),
|
||||
)
|
||||
.unwrap(),
|
||||
OrchardHashDomains::MerkleCrh => pallas::Affine::from_xy(
|
||||
pallas::Base::from_bytes(&Q_MERKLE_CRH.0).unwrap(),
|
||||
pallas::Base::from_bytes(&Q_MERKLE_CRH.1).unwrap(),
|
||||
pallas::Base::from_repr(Q_MERKLE_CRH.0).unwrap(),
|
||||
pallas::Base::from_repr(Q_MERKLE_CRH.1).unwrap(),
|
||||
)
|
||||
.unwrap(),
|
||||
}
|
||||
@@ -125,10 +110,10 @@ pub enum OrchardCommitDomains {
|
||||
}
|
||||
|
||||
impl CommitDomains<pallas::Affine, OrchardFixedBases, OrchardHashDomains> for OrchardCommitDomains {
|
||||
fn r(&self) -> OrchardFixedBases {
|
||||
fn r(&self) -> OrchardFixedBasesFull {
|
||||
match self {
|
||||
Self::NoteCommit => OrchardFixedBases::NoteCommitR,
|
||||
Self::CommitIvk => OrchardFixedBases::CommitIvkR,
|
||||
Self::NoteCommit => OrchardFixedBasesFull::NoteCommitR,
|
||||
Self::CommitIvk => OrchardFixedBasesFull::CommitIvkR,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,23 +128,19 @@ impl CommitDomains<pallas::Affine, OrchardFixedBases, OrchardHashDomains> for Or
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::crypto::constants::{
|
||||
use crate::constants::{
|
||||
fixed_bases::{COMMIT_IVK_PERSONALIZATION, NOTE_COMMITMENT_PERSONALIZATION},
|
||||
sinsemilla::MERKLE_CRH_PERSONALIZATION,
|
||||
};
|
||||
use group::{ff::PrimeField, Curve};
|
||||
use halo2_gadgets::primitives::sinsemilla::{CommitDomain, HashDomain};
|
||||
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, FieldExt},
|
||||
group::{ff::PrimeField, Curve},
|
||||
pallas,
|
||||
};
|
||||
use halo2_proofs::{arithmetic::CurveAffine, pasta::pallas};
|
||||
use rand::{self, rngs::OsRng, Rng};
|
||||
|
||||
#[test]
|
||||
// Nodes in the Merkle tree are Pallas base field elements.
|
||||
fn l_orchard_merkle() {
|
||||
assert_eq!(255, pallas::Base::NUM_BITS as usize);
|
||||
assert_eq!(super::L_ORCHARD_MERKLE, pallas::Base::NUM_BITS as usize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -198,14 +179,8 @@ mod tests {
|
||||
let point = domain.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()
|
||||
);
|
||||
assert_eq!(*coords.x(), pallas::Base::from_repr(Q_NOTE_COMMITMENT_M_GENERATOR.0).unwrap());
|
||||
assert_eq!(*coords.y(), pallas::Base::from_repr(Q_NOTE_COMMITMENT_M_GENERATOR.1).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -214,8 +189,8 @@ mod tests {
|
||||
let point = domain.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());
|
||||
assert_eq!(*coords.x(), pallas::Base::from_repr(Q_COMMIT_IVK_M_GENERATOR.0).unwrap());
|
||||
assert_eq!(*coords.y(), pallas::Base::from_repr(Q_COMMIT_IVK_M_GENERATOR.1).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -224,14 +199,14 @@ mod tests {
|
||||
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());
|
||||
assert_eq!(*coords.x(), pallas::Base::from_repr(Q_MERKLE_CRH.0).unwrap());
|
||||
assert_eq!(*coords.y(), pallas::Base::from_repr(Q_MERKLE_CRH.1).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inv_two_pow_k() {
|
||||
let two_pow_k = pallas::Base::from_u64(1u64 << K);
|
||||
let inv_two_pow_k = pallas::Base::from_bytes(&INV_TWO_POW_K).unwrap();
|
||||
let two_pow_k = pallas::Base::from(1u64 << K);
|
||||
let inv_two_pow_k = pallas::Base::from_repr(INV_TWO_POW_K).unwrap();
|
||||
|
||||
assert_eq!(two_pow_k * inv_two_pow_k, pallas::Base::one());
|
||||
}
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
use pasta_curves::arithmetic::{CurveAffine, Field, FieldExt};
|
||||
|
||||
/// 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().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
|
||||
/// type `Output`.
|
||||
pub fn gen_const_array<Output: Copy + Default, const LEN: usize>(
|
||||
@@ -16,10 +8,10 @@ pub fn gen_const_array<Output: Copy + Default, const LEN: usize>(
|
||||
|
||||
pub(crate) fn gen_const_array_with_default<Output: Copy, const LEN: usize>(
|
||||
default_value: Output,
|
||||
closure: impl FnMut(usize) -> Output,
|
||||
mut closure: impl FnMut(usize) -> Output,
|
||||
) -> [Output; LEN] {
|
||||
let mut ret: [Output; LEN] = [default_value; LEN];
|
||||
for (bit, val) in ret.iter_mut().zip((0..LEN).map(closure)) {
|
||||
for (bit, val) in ret.iter_mut().zip((0..LEN).map(|idx| closure(idx))) {
|
||||
*bit = val;
|
||||
}
|
||||
ret
|
||||
|
||||
Reference in New Issue
Block a user