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::Secp256k1;
13
14const CURVE_B: Secp256k1Coord = Secp256k1Coord::from_const_bytes(seven_le());
17pub const fn seven_le() -> [u8; 32] {
18 let mut buf = [0u8; 32];
19 buf[0] = 7;
20 buf
21}
22
23moduli_declare! {
24 Secp256k1Coord { modulus = "0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F" },
25 Secp256k1Scalar { modulus = "0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141" },
26}
27
28sw_declare! {
29 Secp256k1Point { mod_type = Secp256k1Coord, b = CURVE_B },
30}
31
32impl CyclicGroup for Secp256k1Point {
35 const GENERATOR: Self = Secp256k1Point {
37 x: Secp256k1Coord::from_const_bytes(hex!(
39 "9817F8165B81F259D928CE2DDBFC9B02070B87CE9562A055ACBBDCF97E66BE79"
40 )),
41 y: Secp256k1Coord::from_const_bytes(hex!(
42 "B8D410FB8FD0479C195485A648B417FDA808110EFCFBA45D65C4A32677DA3A48"
43 )),
44 };
45 const NEG_GENERATOR: Self = Secp256k1Point {
46 x: Secp256k1Coord::from_const_bytes(hex!(
47 "9817F8165B81F259D928CE2DDBFC9B02070B87CE9562A055ACBBDCF97E66BE79"
48 )),
49 y: Secp256k1Coord::from_const_bytes(hex!(
50 "7727EF046F2FB863E6AB7A59B74BE80257F7EEF103045BA29A3B5CD98825C5B7"
51 )),
52 };
53}
54
55impl IntrinsicCurve for Secp256k1 {
56 type Scalar = Secp256k1Scalar;
57 type Point = Secp256k1Point;
58
59 fn msm(coeffs: &[Self::Scalar], bases: &[Self::Point]) -> Self::Point
60 where
61 for<'a> &'a Self::Point: Add<&'a Self::Point, Output = Self::Point>,
62 {
63 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 Secp256k1Point {
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}