cairo_lang_sierra/extensions/modules/starknet/
secp256.rs

1use std::marker::PhantomData;
2
3use super::secp256k1::{Secp256k1, Secp256k1PointType};
4use super::secp256r1::{Secp256r1, Secp256r1PointType};
5use super::syscalls::SyscallGenericLibfunc;
6use crate::extensions::enm::EnumType;
7use crate::extensions::lib_func::SignatureSpecializationContext;
8use crate::extensions::modules::{get_bool_type, get_u256_type, get_unit_type};
9use crate::extensions::{NamedType, SpecializationError};
10use crate::ids::{GenericTypeId, UserTypeId};
11use crate::program::GenericArg;
12use crate::{define_libfunc_hierarchy, define_type_hierarchy};
13
14define_type_hierarchy! {
15    pub enum Secp256PointType {
16        K1(Secp256k1PointType),
17        R1(Secp256r1PointType),
18    }, Secp256PointTypeConcrete
19}
20
21pub trait Secp256Trait: Default {
22    const STR_ID_NEW: &'static str;
23    const STR_ID_ADD: &'static str;
24    const STR_ID_MUL: &'static str;
25    const STR_ID_GET_POINT_FROM_X: &'static str;
26    const STR_ID_GET_XY: &'static str;
27    const TYPE_ID: GenericTypeId;
28    const TYPE_ID_STR: &'static str;
29}
30define_libfunc_hierarchy! {
31    pub enum Secp256Libfunc {
32        K1(Secp256OpLibfunc<Secp256k1>),
33        R1(Secp256OpLibfunc<Secp256r1>),
34    }, Secp256ConcreteLibfunc
35}
36define_libfunc_hierarchy! {
37    pub enum Secp256OpLibfunc<T: Secp256Trait> {
38        New(Secp256NewLibfunc<T>),
39        Add(Secp256AddLibfunc<T>),
40        Mul(Secp256MulLibfunc<T>),
41        GetPointFromX(Secp256GetPointFromXLibfunc<T>),
42        GetXy(Secp256GetXyLibfunc<T>),
43    }, Secp256OpConcreteLibfunc
44}
45
46/// System call libfunc for creating a point on the secp256 elliptic curve.
47#[derive(Default)]
48pub struct Secp256NewLibfunc<T: Secp256Trait> {
49    _phantom: PhantomData<T>,
50}
51impl<T: Secp256Trait> SyscallGenericLibfunc for Secp256NewLibfunc<T> {
52    const STR_ID: &'static str = T::STR_ID_NEW;
53
54    fn input_tys(
55        context: &dyn SignatureSpecializationContext,
56    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
57        let u256_ty = get_u256_type(context)?;
58        // `x` coordinate, `y` coordinate.
59        Ok(vec![u256_ty.clone(), u256_ty])
60    }
61
62    fn success_output_tys(
63        context: &dyn SignatureSpecializationContext,
64    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
65        optional_secp256_ec_point_return_type::<T>(context)
66    }
67}
68
69/// Libfunc for a secp256 elliptic curve addition system call.
70#[derive(Default)]
71pub struct Secp256AddLibfunc<T: Secp256Trait> {
72    _phantom: PhantomData<T>,
73}
74impl<T: Secp256Trait> SyscallGenericLibfunc for Secp256AddLibfunc<T> {
75    const STR_ID: &'static str = T::STR_ID_ADD;
76
77    fn input_tys(
78        context: &dyn SignatureSpecializationContext,
79    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
80        let secp256_ec_point_type = context.get_concrete_type(T::TYPE_ID, &[])?;
81
82        // Point `p0`, point `p1`.
83        Ok(vec![secp256_ec_point_type.clone(), secp256_ec_point_type])
84    }
85
86    fn success_output_tys(
87        context: &dyn SignatureSpecializationContext,
88    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
89        Ok(vec![context.get_concrete_type(T::TYPE_ID, &[])?])
90    }
91}
92
93/// Libfunc for a secp256 elliptic curve multiplication system call.
94#[derive(Default)]
95pub struct Secp256MulLibfunc<T: Secp256Trait> {
96    _phantom: PhantomData<T>,
97}
98impl<T: Secp256Trait> SyscallGenericLibfunc for Secp256MulLibfunc<T> {
99    const STR_ID: &'static str = T::STR_ID_MUL;
100
101    fn input_tys(
102        context: &dyn SignatureSpecializationContext,
103    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
104        Ok(vec![
105            // Point `p`.
106            context.get_concrete_type(T::TYPE_ID, &[])?,
107            // Scalar `scalar`.
108            get_u256_type(context)?,
109        ])
110    }
111
112    fn success_output_tys(
113        context: &dyn SignatureSpecializationContext,
114    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
115        Ok(vec![context.get_concrete_type(T::TYPE_ID, &[])?])
116    }
117}
118
119/// System call libfunc for getting a point on the secp256 elliptic curve, according to the given
120/// `x` coordinate and the parity of the relevant y coordinate.
121#[derive(Default)]
122pub struct Secp256GetPointFromXLibfunc<T: Secp256Trait> {
123    _phantom: PhantomData<T>,
124}
125impl<T: Secp256Trait> SyscallGenericLibfunc for Secp256GetPointFromXLibfunc<T> {
126    const STR_ID: &'static str = T::STR_ID_GET_POINT_FROM_X;
127
128    fn input_tys(
129        context: &dyn SignatureSpecializationContext,
130    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
131        Ok(vec![
132            // `x` coordinate.
133            get_u256_type(context)?,
134            // `y_parity` - parity of the relevant y coordinate.
135            get_bool_type(context)?,
136        ])
137    }
138
139    fn success_output_tys(
140        context: &dyn SignatureSpecializationContext,
141    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
142        optional_secp256_ec_point_return_type::<T>(context)
143    }
144}
145
146/// System call libfunc for getting the coordinates of a point on the secp256 elliptic curve.
147#[derive(Default)]
148
149pub struct Secp256GetXyLibfunc<T: Secp256Trait> {
150    _phantom: PhantomData<T>,
151}
152impl<T: Secp256Trait> SyscallGenericLibfunc for Secp256GetXyLibfunc<T> {
153    const STR_ID: &'static str = T::STR_ID_GET_XY;
154
155    fn input_tys(
156        context: &dyn SignatureSpecializationContext,
157    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
158        Ok(vec![
159            // Point `p`.
160            context.get_concrete_type(T::TYPE_ID, &[])?,
161        ])
162    }
163
164    fn success_output_tys(
165        context: &dyn SignatureSpecializationContext,
166    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
167        Ok(vec![
168            // `x` coordinate.
169            get_u256_type(context)?,
170            // `y` coordinate.
171            get_u256_type(context)?,
172        ])
173    }
174}
175
176/// Returns a single return type of `Option<Secp256Point>`.
177fn optional_secp256_ec_point_return_type<T: Secp256Trait>(
178    context: &dyn SignatureSpecializationContext,
179) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
180    let secp256_ec_point_type = context.get_concrete_type(T::TYPE_ID, &[])?;
181
182    let unit_type = get_unit_type(context)?;
183    // TODO(yuval): add get_option_type to mod.rs and use it here.
184    let option_secp256_ec_point_type = context.get_concrete_type(EnumType::id(), &[
185        GenericArg::UserType(UserTypeId::from_string(format!(
186            "core::option::Option::<{}>",
187            T::TYPE_ID_STR
188        ))),
189        GenericArg::Type(secp256_ec_point_type),
190        GenericArg::Type(unit_type),
191    ])?;
192    Ok(vec![option_secp256_ec_point_type])
193}