Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add functions to evaluate a Sinsemilla hash from an initial private point #22

Merged
merged 3 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 61 additions & 1 deletion halo2_gadgets/src/sinsemilla.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
/// This returns both the resulting point, as well as the message
/// decomposition in the form of intermediate values in a cumulative
/// sum.
///
/// The initial point `Q` is a public point.
#[allow(non_snake_case)]
#[allow(clippy::type_complexity)]
fn hash_to_point(
Expand All @@ -88,6 +88,20 @@
message: Self::Message,
) -> Result<(Self::NonIdentityPoint, Vec<Self::RunningSum>), Error>;

/// Hashes a message to an ECC curve point.
/// This returns both the resulting point, as well as the message
/// decomposition in the form of intermediate values in a cumulative
/// sum.
/// The initial point `Q` is a private point.
#[allow(non_snake_case)]
#[allow(clippy::type_complexity)]
fn hash_to_point_with_private_init(
&self,
layouter: impl Layouter<C::Base>,
Q: &Self::NonIdentityPoint,
message: Self::Message,
) -> Result<(Self::NonIdentityPoint, Vec<Self::RunningSum>), Error>;

/// Extracts the x-coordinate of the output of a Sinsemilla hash.
fn extract(point: &Self::NonIdentityPoint) -> Self::X;
}
Expand Down Expand Up @@ -329,6 +343,23 @@
.map(|(point, zs)| (ecc::NonIdentityPoint::from_inner(self.ecc_chip.clone(), point), zs))
}

#[allow(non_snake_case)]
#[allow(clippy::type_complexity)]
/// $\mathsf{SinsemillaHashToPoint}$ from [§ 5.4.1.9][concretesinsemillahash].
///
/// [concretesinsemillahash]: https://zips.z.cash/protocol/protocol.pdf#concretesinsemillahash
ConstanceBeguier marked this conversation as resolved.
Show resolved Hide resolved
pub fn hash_to_point_with_private_init(
ConstanceBeguier marked this conversation as resolved.
Show resolved Hide resolved
&self,
layouter: impl Layouter<C::Base>,
Q: &<SinsemillaChip as SinsemillaInstructions<C, K, MAX_WORDS>>::NonIdentityPoint,
message: Message<C, SinsemillaChip, K, MAX_WORDS>,
) -> Result<(ecc::NonIdentityPoint<C, EccChip>, Vec<SinsemillaChip::RunningSum>), Error> {
assert_eq!(self.sinsemilla_chip, message.chip);
self.sinsemilla_chip
.hash_to_point_with_private_init(layouter, Q, message.inner)
.map(|(point, zs)| (ecc::NonIdentityPoint::from_inner(self.ecc_chip.clone(), point), zs))
}

/// $\mathsf{SinsemillaHash}$ from [§ 5.4.1.9][concretesinsemillahash].
///
/// [concretesinsemillahash]: https://zips.z.cash/protocol/protocol.pdf#concretesinsemillahash
Expand Down Expand Up @@ -431,6 +462,35 @@
self.M.hash_to_point(layouter, message)
}

#[allow(non_snake_case)]
#[allow(clippy::type_complexity)]
/// $\mathsf{SinsemillaCommit}$ from [§ 5.4.8.4][concretesinsemillacommit].
///
/// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit
pub fn hash_with_private_init(
&self,
layouter: impl Layouter<C::Base>,
Q: &<SinsemillaChip as SinsemillaInstructions<C, K, MAX_WORDS>>::NonIdentityPoint,
message: Message<C, SinsemillaChip, K, MAX_WORDS>,
) -> Result<
(
ecc::NonIdentityPoint<C, EccChip>,
Vec<SinsemillaChip::RunningSum>,
),
Error,
> {
assert_eq!(self.M.sinsemilla_chip, message.chip);
self.M.hash_to_point_with_private_init(layouter, Q, message)
}

#[allow(clippy::type_complexity)]
/// $\mathsf{SinsemillaCommit}$ from [§ 5.4.8.4][concretesinsemillacommit].
///
/// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit
pub fn q_init(&self) -> C {
self.M.Q
}

#[allow(clippy::type_complexity)]
/// $\mathsf{SinsemillaCommit}$ from [§ 5.4.8.4][concretesinsemillacommit].
///
Expand Down Expand Up @@ -697,8 +757,8 @@
let point = merkle_crh
.hash_to_point(
l.into_iter()
.chain(left.into_iter())

Check warning on line 760 in halo2_gadgets/src/sinsemilla.rs

View workflow job for this annotation

GitHub Actions / Clippy (beta)

explicit call to `.into_iter()` in function argument accepting `IntoIterator`

warning: explicit call to `.into_iter()` in function argument accepting `IntoIterator` --> halo2_gadgets/src/sinsemilla.rs:760:48 | 760 | ... .chain(left.into_iter()) | ^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `left` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` --> /rustc/9326de8faf0305dd905b266b4ea0a3b990123a5b/library/core/src/iter/traits/iterator.rs:523:12 = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion = note: `-W clippy::useless-conversion` implied by `-W clippy::all` = help: to override `-W clippy::all` add `#[allow(clippy::useless_conversion)]`
.chain(right.into_iter()),

Check warning on line 761 in halo2_gadgets/src/sinsemilla.rs

View workflow job for this annotation

GitHub Actions / Clippy (beta)

explicit call to `.into_iter()` in function argument accepting `IntoIterator`

warning: explicit call to `.into_iter()` in function argument accepting `IntoIterator` --> halo2_gadgets/src/sinsemilla.rs:761:48 | 761 | ... .chain(right.into_iter()), | ^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `right` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` --> /rustc/9326de8faf0305dd905b266b4ea0a3b990123a5b/library/core/src/iter/traits/iterator.rs:523:12 = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion
)
.unwrap();
point.to_affine()
Expand Down
37 changes: 35 additions & 2 deletions halo2_gadgets/src/sinsemilla/chip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ where
/// q_sinsemilla2 is used to define a synthetic selector,
/// q_sinsemilla3 = (q_sinsemilla2) ⋅ (q_sinsemilla2 - 1)
/// Simple selector used to constrain hash initialization to be consistent with
/// the y-coordinate of the domain $Q$.
/// the y-coordinate of the domain $Q$ when $y_Q$ is a public constant.
q_sinsemilla4: Selector,
/// Simple selector used to constrain hash initialization to be consistent with
/// the y-coordinate of the domain $Q$ when $y_Q$ is a private value.
q_sinsemilla4_private: Selector,
/// Fixed column used to load the y-coordinate of the domain $Q$.
fixed_y_q: Column<Fixed>,
/// Logic specific to merged double-and-add.
Expand Down Expand Up @@ -165,6 +168,7 @@ where
q_sinsemilla1: meta.complex_selector(),
q_sinsemilla2: meta.fixed_column(),
q_sinsemilla4: meta.selector(),
q_sinsemilla4_private: meta.selector(),
fixed_y_q,
double_and_add: DoubleAndAdd {
x_a: advices[0],
Expand Down Expand Up @@ -202,7 +206,7 @@ where

// Check that the initial x_A, x_P, lambda_1, lambda_2 are consistent with y_Q.
// https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial
meta.create_gate("Initial y_Q", |meta| {
meta.create_gate("Initial y_Q (public)", |meta| {
let q_s4 = meta.query_selector(config.q_sinsemilla4);
let y_q = meta.query_fixed(config.fixed_y_q);

Expand All @@ -215,6 +219,21 @@ where
Constraints::with_selector(q_s4, Some(("init_y_q_check", init_y_q_check)))
});

// Check that the initial x_A, x_P, lambda_1, lambda_2 are consistent with y_Q.
// https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial
meta.create_gate("Initial y_Q (private)", |meta| {
let q_s4 = meta.query_selector(config.q_sinsemilla4_private);
let y_q = meta.query_advice(config.double_and_add.x_p, Rotation::prev());

// Y_A = (lambda_1 + lambda_2) * (x_a - x_r)
let Y_A_cur = Y_A(meta, Rotation::cur());

// 2 * y_q - Y_{A,0} = 0
let init_y_q_check = y_q * two - Y_A_cur;

Constraints::with_selector(q_s4, Some(("init_y_q_check", init_y_q_check)))
});

// https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial
meta.create_gate("Sinsemilla gate", |meta| {
let q_s1 = meta.query_selector(config.q_sinsemilla1);
Expand Down Expand Up @@ -322,6 +341,20 @@ where
)
}

#[allow(non_snake_case)]
#[allow(clippy::type_complexity)]
fn hash_to_point_with_private_init(
&self,
mut layouter: impl Layouter<pallas::Base>,
Q: &Self::NonIdentityPoint,
message: Self::Message,
) -> Result<(Self::NonIdentityPoint, Vec<Self::RunningSum>), Error> {
layouter.assign_region(
|| "hash_to_point",
|mut region| self.hash_message_with_private_init(&mut region, Q, &message),
)
}

fn extract(point: &Self::NonIdentityPoint) -> Self::X {
point.x()
}
Expand Down
Loading
Loading