k256/
internal.rs

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
14// --- Define the OpenVM modular arithmetic and ecc types ---
15
16const 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
32// --- Implement internal traits ---
33
34impl CyclicGroup for Secp256k1Point {
35    // The constants are taken from: https://en.bitcoin.it/wiki/Secp256k1
36    const GENERATOR: Self = Secp256k1Point {
37        // from_const_bytes takes a little endian byte string
38        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        // heuristic
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
73// --- Implement helpful methods mimicking the structs in k256 ---
74
75impl 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}