use crypto_bigint::{impl_modulus, U256};
impl_modulus!(
PMod,
U256,
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF"
);
impl_modulus!(
NMod,
U256,
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123"
);
pub type Fp = crypto_bigint::modular::ConstMontyForm<PMod, { U256::LIMBS }>;
pub type Fn = crypto_bigint::modular::ConstMontyForm<NMod, { U256::LIMBS }>;
pub(crate) const B_HEX: &str = "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93";
#[allow(dead_code)]
pub(crate) const GX_HEX: &str = "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7";
#[allow(dead_code)]
pub(crate) const GY_HEX: &str = "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0";
#[must_use]
pub const fn b() -> Fp {
Fp::new(&U256::from_be_hex(B_HEX))
}
#[must_use]
pub fn b3() -> Fp {
let b = b();
b + b + b
}
#[cfg(test)]
mod tests {
use super::*;
use crypto_bigint::modular::ConstMontyParams;
use crypto_bigint::Invert;
#[test]
fn moduli_are_correct_size() {
assert_eq!(PMod::MODULUS.bits(), 256);
assert_eq!(NMod::MODULUS.bits(), 256);
}
#[test]
fn b_is_not_zero() {
let b = b();
assert_ne!(b.retrieve(), U256::ZERO);
}
#[test]
fn b3_equals_3b() {
let b = b();
let b3 = b3();
assert_eq!(b3.retrieve(), (b + b + b).retrieve());
}
#[test]
fn fp_invert_round_trip() {
let a = Fp::new(&U256::from_u64(7));
let a_inv = a.invert().expect("7 is invertible mod p");
let one = Fp::new(&U256::ONE);
assert_eq!((a * a_inv).retrieve(), one.retrieve());
}
#[test]
fn fn_invert_round_trip() {
let a = Fn::new(&U256::from_u64(5));
let a_inv = a.invert().expect("5 is invertible mod n");
let one = Fn::new(&U256::ONE);
assert_eq!((a * a_inv).retrieve(), one.retrieve());
}
#[test]
fn invert_zero_is_none() {
let zero = Fp::new(&U256::ZERO);
assert!(bool::from(zero.invert().is_none()));
}
}