pathfinder_common/
class_definition.rs

1use std::borrow::Cow;
2use std::fmt;
3
4use fake::{Dummy, Fake, Faker};
5use pathfinder_crypto::Felt;
6use rand::Rng;
7use serde::{Deserialize, Serialize};
8use serde_json::value::RawValue;
9use serde_with::serde_as;
10
11use crate::{ByteCodeOffset, EntryPoint};
12
13pub const CLASS_DEFINITION_MAX_ALLOWED_SIZE: u64 = 4 * 1024 * 1024;
14
15#[derive(Debug, Deserialize, Dummy)]
16pub enum ClassDefinition<'a> {
17    Sierra(Sierra<'a>),
18    Cairo(Cairo<'a>),
19}
20
21#[derive(Debug, Deserialize, Serialize)]
22#[serde(deny_unknown_fields)]
23pub struct Sierra<'a> {
24    /// Contract ABI.
25    pub abi: Cow<'a, str>,
26
27    /// Main program definition.
28    pub sierra_program: Vec<Felt>,
29
30    // Version
31    pub contract_class_version: Cow<'a, str>,
32
33    /// The contract entry points
34    pub entry_points_by_type: SierraEntryPoints,
35}
36
37impl<T> Dummy<T> for Sierra<'_> {
38    fn dummy_with_rng<R: Rng + ?Sized>(_: &T, rng: &mut R) -> Self {
39        Self {
40            abi: "[]".into(),
41            sierra_program: Faker.fake_with_rng(rng),
42            contract_class_version: "0.1.0".into(),
43            entry_points_by_type: Faker.fake_with_rng(rng),
44        }
45    }
46}
47
48#[derive(Debug, Deserialize, Serialize)]
49#[serde(deny_unknown_fields)]
50pub struct Cairo<'a> {
51    /// Contract ABI, which has no schema definition.
52    pub abi: Cow<'a, RawValue>,
53
54    /// Main program definition. __We assume that this is valid JSON.__
55    pub program: Cow<'a, RawValue>,
56
57    /// The contract entry points.
58    pub entry_points_by_type: CairoEntryPoints,
59}
60
61impl<T> Dummy<T> for Cairo<'_> {
62    fn dummy_with_rng<R: Rng + ?Sized>(_: &T, rng: &mut R) -> Self {
63        Self {
64            abi: Cow::Owned(
65                RawValue::from_string("[]".into()).unwrap(),
66            ),
67            program: Cow::Owned(
68                RawValue::from_string(
69                    r#"
70                    {
71                        "attributes": [],
72                        "builtins": [],
73                        "data": [],
74                        "debug_info": null,
75                        "hints": {},
76                        "identifiers": {},
77                        "main_scope": "__main__",
78                        "prime": "0x800000000000011000000000000000000000000000000000000000000000001",
79                        "reference_manager": {}
80                    }
81                    "#.into()
82                )
83                .unwrap(),
84            ),
85            entry_points_by_type: Faker.fake_with_rng(rng),
86        }
87    }
88}
89
90#[derive(Debug, Clone, Deserialize, Serialize, Dummy)]
91#[serde(deny_unknown_fields)]
92pub struct SierraEntryPoints {
93    #[serde(rename = "EXTERNAL")]
94    pub external: Vec<SelectorAndFunctionIndex>,
95    #[serde(rename = "L1_HANDLER")]
96    pub l1_handler: Vec<SelectorAndFunctionIndex>,
97    #[serde(rename = "CONSTRUCTOR")]
98    pub constructor: Vec<SelectorAndFunctionIndex>,
99}
100
101#[derive(Debug, Deserialize, Serialize, Dummy)]
102#[serde(deny_unknown_fields)]
103pub struct CairoEntryPoints {
104    #[serde(rename = "EXTERNAL")]
105    pub external: Vec<SelectorAndOffset>,
106    #[serde(rename = "L1_HANDLER")]
107    pub l1_handler: Vec<SelectorAndOffset>,
108    #[serde(rename = "CONSTRUCTOR")]
109    pub constructor: Vec<SelectorAndOffset>,
110}
111
112#[derive(Copy, Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq, Hash, Eq)]
113#[serde(deny_unknown_fields)]
114pub enum EntryPointType {
115    #[serde(rename = "EXTERNAL")]
116    External,
117    #[serde(rename = "L1_HANDLER")]
118    L1Handler,
119    #[serde(rename = "CONSTRUCTOR")]
120    Constructor,
121}
122
123impl fmt::Display for EntryPointType {
124    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125        use EntryPointType::*;
126        f.pad(match self {
127            External => "EXTERNAL",
128            L1Handler => "L1_HANDLER",
129            Constructor => "CONSTRUCTOR",
130        })
131    }
132}
133
134#[serde_as]
135#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq)]
136#[serde(deny_unknown_fields)]
137pub struct SelectorAndOffset {
138    pub selector: EntryPoint,
139    #[serde_as(as = "OffsetSerde")]
140    pub offset: ByteCodeOffset,
141}
142
143#[derive(serde::Deserialize, serde::Serialize)]
144#[serde(untagged)]
145pub enum OffsetSerde {
146    HexStr(Felt),
147    Decimal(u64),
148}
149
150impl serde_with::SerializeAs<ByteCodeOffset> for OffsetSerde {
151    fn serialize_as<S>(source: &ByteCodeOffset, serializer: S) -> Result<S::Ok, S::Error>
152    where
153        S: serde::Serializer,
154    {
155        use serde::Serialize;
156
157        Felt::serialize(&source.0, serializer)
158    }
159}
160
161impl<'de> serde_with::DeserializeAs<'de, ByteCodeOffset> for OffsetSerde {
162    fn deserialize_as<D>(deserializer: D) -> Result<ByteCodeOffset, D::Error>
163    where
164        D: serde::Deserializer<'de>,
165    {
166        use serde::Deserialize;
167
168        let offset = OffsetSerde::deserialize(deserializer)?;
169        let offset = match offset {
170            OffsetSerde::HexStr(felt) => felt,
171            OffsetSerde::Decimal(decimal) => Felt::from_u64(decimal),
172        };
173        Ok(ByteCodeOffset(offset))
174    }
175}
176
177impl<T> Dummy<T> for SelectorAndOffset {
178    fn dummy_with_rng<R: rand::prelude::Rng + ?Sized>(_: &T, rng: &mut R) -> Self {
179        Self {
180            selector: Faker.fake_with_rng(rng),
181            offset: ByteCodeOffset(Felt::from_u64(rng.gen())),
182        }
183    }
184}
185
186/// Descriptor of an entry point in a Sierra class.
187#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, Dummy)]
188#[serde(deny_unknown_fields)]
189pub struct SelectorAndFunctionIndex {
190    pub selector: EntryPoint,
191    pub function_idx: u64,
192}