Skip to content

Commit

Permalink
order functions in hash_to_point
Browse files Browse the repository at this point in the history
  • Loading branch information
YaoGalteland committed Jun 4, 2024
1 parent b252579 commit ce24e86
Showing 1 changed file with 74 additions and 74 deletions.
148 changes: 74 additions & 74 deletions halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,80 @@ where
self.check_hash_result(EccPointQ::PublicPoint(Q), message, x_a, y_a, zs_sum)
}

#[allow(unused_variables)]
#[allow(non_snake_case)]
#[allow(clippy::type_complexity)]
fn check_hash_result(
&self,
Q: EccPointQ,
message: &<Self as SinsemillaInstructions<
pallas::Affine,
{ sinsemilla::K },
{ sinsemilla::C },
>>::Message,
x_a: X<pallas::Base>,
y_a: AssignedCell<Assigned<pallas::Base>, pallas::Base>,
zs_sum: Vec<Vec<AssignedCell<pallas::Base, pallas::Base>>>,
) -> Result<
(
NonIdentityEccPoint,
Vec<Vec<AssignedCell<pallas::Base, pallas::Base>>>,
),
Error,
> {
#[cfg(test)]
// Check equivalence to result from primitives::sinsemilla::hash_to_point
{
use crate::sinsemilla::primitives::{K, S_PERSONALIZATION};

use group::{prime::PrimeCurveAffine, Curve};
use pasta_curves::arithmetic::CurveExt;

let field_elems: Value<Vec<_>> = message
.iter()
.map(|piece| piece.field_elem().map(|elem| (elem, piece.num_words())))
.collect();

let value_Q = match Q {
EccPointQ::PublicPoint(p) => Value::known(p),
EccPointQ::PrivatePoint(p) => p.point(),
};

field_elems
.zip(x_a.value().zip(y_a.value()))
.zip(value_Q)
.assert_if_known(|((field_elems, (x_a, y_a)), value_Q)| {
// Get message as a bitstring.
let bitstring: Vec<bool> = field_elems
.iter()
.flat_map(|(elem, num_words)| {
elem.to_le_bits().into_iter().take(K * num_words)
})
.collect();

let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION);
let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes());

// We can use complete addition here because it differs from
// incomplete addition with negligible probability.
let expected_point = bitstring
.chunks(K)
.fold(value_Q.to_curve(), |acc, chunk| (acc + S(chunk)) + acc);
let actual_point =
pallas::Affine::from_xy(x_a.evaluate(), y_a.evaluate()).unwrap();
expected_point.to_affine() == actual_point
});
}

x_a.value()
.zip(y_a.value())
.error_if_known_and(|(x_a, y_a)| x_a.is_zero_vartime() || y_a.is_zero_vartime())?;
Ok((
NonIdentityEccPoint::from_coordinates_unchecked(x_a.0, y_a),
zs_sum,
))
}

#[allow(non_snake_case)]
/// Assign the coordinates of the initial public point `Q`,
/// y_Q to a fixed column
Expand Down Expand Up @@ -179,80 +253,6 @@ where
Ok((x_a, y_a, zs_sum))
}

#[allow(unused_variables)]
#[allow(non_snake_case)]
#[allow(clippy::type_complexity)]
fn check_hash_result(
&self,
Q: EccPointQ,
message: &<Self as SinsemillaInstructions<
pallas::Affine,
{ sinsemilla::K },
{ sinsemilla::C },
>>::Message,
x_a: X<pallas::Base>,
y_a: AssignedCell<Assigned<pallas::Base>, pallas::Base>,
zs_sum: Vec<Vec<AssignedCell<pallas::Base, pallas::Base>>>,
) -> Result<
(
NonIdentityEccPoint,
Vec<Vec<AssignedCell<pallas::Base, pallas::Base>>>,
),
Error,
> {
#[cfg(test)]
// Check equivalence to result from primitives::sinsemilla::hash_to_point
{
use crate::sinsemilla::primitives::{K, S_PERSONALIZATION};

use group::{prime::PrimeCurveAffine, Curve};
use pasta_curves::arithmetic::CurveExt;

let field_elems: Value<Vec<_>> = message
.iter()
.map(|piece| piece.field_elem().map(|elem| (elem, piece.num_words())))
.collect();

let value_Q = match Q {
EccPointQ::PublicPoint(p) => Value::known(p),
EccPointQ::PrivatePoint(p) => p.point(),
};

field_elems
.zip(x_a.value().zip(y_a.value()))
.zip(value_Q)
.assert_if_known(|((field_elems, (x_a, y_a)), value_Q)| {
// Get message as a bitstring.
let bitstring: Vec<bool> = field_elems
.iter()
.flat_map(|(elem, num_words)| {
elem.to_le_bits().into_iter().take(K * num_words)
})
.collect();

let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION);
let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes());

// We can use complete addition here because it differs from
// incomplete addition with negligible probability.
let expected_point = bitstring
.chunks(K)
.fold(value_Q.to_curve(), |acc, chunk| (acc + S(chunk)) + acc);
let actual_point =
pallas::Affine::from_xy(x_a.evaluate(), y_a.evaluate()).unwrap();
expected_point.to_affine() == actual_point
});
}

x_a.value()
.zip(y_a.value())
.error_if_known_and(|(x_a, y_a)| x_a.is_zero_vartime() || y_a.is_zero_vartime())?;
Ok((
NonIdentityEccPoint::from_coordinates_unchecked(x_a.0, y_a),
zs_sum,
))
}

#[allow(clippy::type_complexity)]
/// Hashes a message piece containing `piece.length` number of `K`-bit words.
///
Expand Down

0 comments on commit ce24e86

Please sign in to comment.