1use core::ops::{Add, Neg};
2
3use hex_literal::hex;
4use openvm_algebra_guest::IntMod;
5use openvm_algebra_moduli_macros::moduli_declare;
6use openvm_ecc_guest::{
7 weierstrass::{CachedMulTable, IntrinsicCurve, WeierstrassPoint},
8 CyclicGroup, Group,
9};
10use openvm_ecc_sw_macros::sw_declare;
11
12use crate::NistP256;
13
14moduli_declare! {
17 P256Coord { modulus = "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff" },
18 P256Scalar { modulus = "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551" },
19}
20
21pub const CURVE_A: P256Coord = P256Coord::from_const_bytes(hex!(
23 "fcffffffffffffffffffffff00000000000000000000000001000000ffffffff"
24));
25pub const CURVE_B: P256Coord = P256Coord::from_const_bytes(hex!(
26 "4b60d2273e3cce3bf6b053ccb0061d65bc86987655bdebb3e7933aaad835c65a"
27));
28
29sw_declare! {
30 P256Point { mod_type = P256Coord, a = CURVE_A, b = CURVE_B },
31}
32
33impl CyclicGroup for P256Point {
36 const GENERATOR: Self = P256Point {
38 x: P256Coord::from_const_bytes(hex!(
40 "96c298d84539a1f4a033eb2d817d0377f240a463e5e6bcf847422ce1f2d1176b"
41 )),
42 y: P256Coord::from_const_bytes(hex!(
43 "f551bf376840b6cbce5e316b5733ce2b169e0f7c4aebe78e9b7f1afee242e34f"
44 )),
45 };
46 const NEG_GENERATOR: Self = P256Point {
47 x: P256Coord::from_const_bytes(hex!(
48 "96c298d84539a1f4a033eb2d817d0377f240a463e5e6bcf847422ce1f2d1176b"
49 )),
50 y: P256Coord::from_const_bytes(hex!(
51 "0aae40c897bf493431a1ce94a9cc31d4e961f083b51418716580e5011cbd1cb0"
52 )),
53 };
54}
55
56impl IntrinsicCurve for NistP256 {
57 type Scalar = P256Scalar;
58 type Point = P256Point;
59
60 fn msm(coeffs: &[Self::Scalar], bases: &[Self::Point]) -> Self::Point
61 where
62 for<'a> &'a Self::Point: Add<&'a Self::Point, Output = Self::Point>,
63 {
64 if coeffs.len() < 25 {
65 let table = CachedMulTable::<Self>::new_with_prime_order(bases, 4);
66 table.windowed_mul(coeffs)
67 } else {
68 openvm_ecc_guest::msm(coeffs, bases)
69 }
70 }
71}
72
73impl P256Point {
76 pub fn x_be_bytes(&self) -> [u8; 32] {
77 <Self as WeierstrassPoint>::x(self).to_be_bytes()
78 }
79
80 pub fn y_be_bytes(&self) -> [u8; 32] {
81 <Self as WeierstrassPoint>::y(self).to_be_bytes()
82 }
83}