use blake2s_simd::Params as Blake2sParams;
use group::{cofactor::CofactorGroup, ff::PrimeField, Curve, GroupEncoding, WnafBase, WnafScalar};
use super::{
constants::{
CRH_IVK_PERSONALIZATION, KEY_DIVERSIFICATION_PERSONALIZATION,
NOTE_COMMITMENT_RANDOMNESS_GENERATOR, NULLIFIER_POSITION_GENERATOR, PRF_NF_PERSONALIZATION,
},
group_hash::group_hash,
pedersen_hash::{pedersen_hash, Personalization},
};
const PREPARED_WINDOW_SIZE: usize = 4;
pub(crate) type PreparedBase = WnafBase<jubjub::ExtendedPoint, PREPARED_WINDOW_SIZE>;
pub(crate) type PreparedBaseSubgroup = WnafBase<jubjub::SubgroupPoint, PREPARED_WINDOW_SIZE>;
pub(crate) type PreparedScalar = WnafScalar<jubjub::Scalar, PREPARED_WINDOW_SIZE>;
pub(crate) fn crh_ivk(ak: [u8; 32], nk: [u8; 32]) -> jubjub::Scalar {
let mut h: [u8; 32] = Blake2sParams::new()
.hash_length(32)
.personal(CRH_IVK_PERSONALIZATION)
.to_state()
.update(&ak)
.update(&nk)
.finalize()
.as_bytes()
.try_into()
.expect("output length is correct");
h[31] &= 0b0000_0111;
jubjub::Fr::from_repr(h).unwrap()
}
pub(crate) fn diversify_hash(d: &[u8; 11]) -> Option<jubjub::SubgroupPoint> {
group_hash(d, KEY_DIVERSIFICATION_PERSONALIZATION)
}
pub(crate) fn mixing_pedersen_hash(
cm: jubjub::SubgroupPoint,
position: u64,
) -> jubjub::SubgroupPoint {
cm + (NULLIFIER_POSITION_GENERATOR * jubjub::Fr::from(position))
}
pub(crate) fn prf_nf(nk: &jubjub::SubgroupPoint, rho: &jubjub::SubgroupPoint) -> [u8; 32] {
Blake2sParams::new()
.hash_length(32)
.personal(PRF_NF_PERSONALIZATION)
.to_state()
.update(&nk.to_bytes())
.update(&rho.to_bytes())
.finalize()
.as_bytes()
.try_into()
.expect("output length is correct")
}
pub(crate) fn ka_sapling_derive_public(
sk: &jubjub::Scalar,
b: &jubjub::ExtendedPoint,
) -> jubjub::ExtendedPoint {
ka_sapling_derive_public_prepared(&PreparedScalar::new(sk), &PreparedBase::new(*b))
}
pub(crate) fn ka_sapling_derive_public_prepared(
sk: &PreparedScalar,
b: &PreparedBase,
) -> jubjub::ExtendedPoint {
b * sk
}
pub(crate) fn ka_sapling_derive_public_subgroup_prepared(
sk: &PreparedScalar,
b: &PreparedBaseSubgroup,
) -> jubjub::SubgroupPoint {
b * sk
}
pub(crate) fn ka_sapling_agree(
sk: &jubjub::Scalar,
b: &jubjub::ExtendedPoint,
) -> jubjub::SubgroupPoint {
ka_sapling_agree_prepared(&PreparedScalar::new(sk), &PreparedBase::new(*b))
}
pub(crate) fn ka_sapling_agree_prepared(
sk: &PreparedScalar,
b: &PreparedBase,
) -> jubjub::SubgroupPoint {
(b * sk).clear_cofactor()
}
pub(crate) fn windowed_pedersen_commit<I>(
personalization: Personalization,
s: I,
r: jubjub::Scalar,
) -> jubjub::SubgroupPoint
where
I: IntoIterator<Item = bool>,
{
pedersen_hash(personalization, s) + (NOTE_COMMITMENT_RANDOMNESS_GENERATOR * r)
}
pub(crate) fn extract_p(point: &jubjub::SubgroupPoint) -> bls12_381::Scalar {
Into::<&jubjub::ExtendedPoint>::into(point)
.to_affine()
.get_u()
}