Skip to main content

pathfinder_common/
class_definition.rs

1use std::borrow::Cow;
2use std::fmt;
3
4use bytes::Bytes;
5use fake::{Dummy, Fake, Faker};
6use pathfinder_crypto::Felt;
7use rand::Rng;
8use serde::{Deserialize, Serialize};
9use serde_json::value::RawValue;
10use serde_with::serde_as;
11
12use crate::{ByteCodeOffset, EntryPoint};
13
14pub const CLASS_DEFINITION_MAX_ALLOWED_SIZE: u64 = 4 * 1024 * 1024;
15
16#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
17pub struct SerializedSierraDefinition(Bytes);
18
19#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
20pub struct SerializedCasmDefinition(Bytes);
21
22#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
23pub struct SerializedCairoDefinition(Bytes);
24
25/// Carries the definition of a serialized contract class, either Sierra or
26/// Cairo. The caller does not care which class definition it is.
27#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
28pub struct SerializedOpaqueClassDefinition(Bytes);
29
30/// Carries the definition of a serialized contract class, either Sierra or
31/// Cairo.
32#[derive(Clone, Debug)]
33pub enum SerializedClassDefinition {
34    Sierra(SerializedSierraDefinition),
35    Cairo(SerializedCairoDefinition),
36}
37
38#[derive(Debug, Deserialize, Dummy)]
39pub enum ClassDefinition<'a> {
40    Sierra(Sierra<'a>),
41    Cairo(Cairo<'a>),
42}
43
44#[derive(Debug, Clone, Deserialize, Serialize)]
45#[serde(deny_unknown_fields)]
46pub struct Sierra<'a> {
47    /// Contract ABI.
48    pub abi: Cow<'a, str>,
49
50    /// Main program definition.
51    pub sierra_program: Vec<Felt>,
52
53    // Version
54    pub contract_class_version: Cow<'a, str>,
55
56    /// The contract entry points
57    pub entry_points_by_type: SierraEntryPoints,
58}
59
60impl<T> Dummy<T> for Sierra<'_> {
61    fn dummy_with_rng<R: Rng + ?Sized>(_: &T, rng: &mut R) -> Self {
62        Self {
63            abi: "[]".into(),
64            sierra_program: Faker.fake_with_rng(rng),
65            contract_class_version: "0.1.0".into(),
66            entry_points_by_type: Faker.fake_with_rng(rng),
67        }
68    }
69}
70
71#[derive(Debug, Deserialize, Serialize)]
72#[serde(deny_unknown_fields)]
73pub struct Cairo<'a> {
74    /// Contract ABI, which has no schema definition.
75    pub abi: Cow<'a, RawValue>,
76
77    /// Main program definition. __We assume that this is valid JSON.__
78    pub program: Cow<'a, RawValue>,
79
80    /// The contract entry points.
81    pub entry_points_by_type: CairoEntryPoints,
82}
83
84impl<T> Dummy<T> for Cairo<'_> {
85    fn dummy_with_rng<R: Rng + ?Sized>(_: &T, rng: &mut R) -> Self {
86        Self {
87            abi: Cow::Owned(
88                RawValue::from_string("[]".into()).unwrap(),
89            ),
90            program: Cow::Owned(
91                RawValue::from_string(
92                    r#"
93                    {
94                        "attributes": [],
95                        "builtins": [],
96                        "data": [],
97                        "debug_info": null,
98                        "hints": {},
99                        "identifiers": {},
100                        "main_scope": "__main__",
101                        "prime": "0x800000000000011000000000000000000000000000000000000000000000001",
102                        "reference_manager": {}
103                    }
104                    "#.into()
105                )
106                .unwrap(),
107            ),
108            entry_points_by_type: Faker.fake_with_rng(rng),
109        }
110    }
111}
112
113#[derive(Debug, Clone, Deserialize, Serialize, Dummy)]
114#[serde(deny_unknown_fields)]
115pub struct SierraEntryPoints {
116    #[serde(rename = "EXTERNAL")]
117    pub external: Vec<SelectorAndFunctionIndex>,
118    #[serde(rename = "L1_HANDLER")]
119    pub l1_handler: Vec<SelectorAndFunctionIndex>,
120    #[serde(rename = "CONSTRUCTOR")]
121    pub constructor: Vec<SelectorAndFunctionIndex>,
122}
123
124#[derive(Debug, Deserialize, Serialize, Dummy)]
125#[serde(deny_unknown_fields)]
126pub struct CairoEntryPoints {
127    #[serde(rename = "EXTERNAL")]
128    pub external: Vec<SelectorAndOffset>,
129    #[serde(rename = "L1_HANDLER")]
130    pub l1_handler: Vec<SelectorAndOffset>,
131    #[serde(rename = "CONSTRUCTOR")]
132    pub constructor: Vec<SelectorAndOffset>,
133}
134
135#[derive(Copy, Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq, Hash, Eq)]
136#[serde(deny_unknown_fields)]
137pub enum EntryPointType {
138    #[serde(rename = "EXTERNAL")]
139    External,
140    #[serde(rename = "L1_HANDLER")]
141    L1Handler,
142    #[serde(rename = "CONSTRUCTOR")]
143    Constructor,
144}
145
146impl fmt::Display for EntryPointType {
147    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148        use EntryPointType::*;
149        f.pad(match self {
150            External => "EXTERNAL",
151            L1Handler => "L1_HANDLER",
152            Constructor => "CONSTRUCTOR",
153        })
154    }
155}
156
157#[serde_as]
158#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq)]
159#[serde(deny_unknown_fields)]
160pub struct SelectorAndOffset {
161    pub selector: EntryPoint,
162    #[serde_as(as = "OffsetSerde")]
163    pub offset: ByteCodeOffset,
164}
165
166#[derive(serde::Deserialize, serde::Serialize)]
167#[serde(untagged)]
168pub enum OffsetSerde {
169    HexStr(Felt),
170    Decimal(u64),
171}
172
173impl serde_with::SerializeAs<ByteCodeOffset> for OffsetSerde {
174    fn serialize_as<S>(source: &ByteCodeOffset, serializer: S) -> Result<S::Ok, S::Error>
175    where
176        S: serde::Serializer,
177    {
178        use serde::Serialize;
179
180        Felt::serialize(&source.0, serializer)
181    }
182}
183
184impl<'de> serde_with::DeserializeAs<'de, ByteCodeOffset> for OffsetSerde {
185    fn deserialize_as<D>(deserializer: D) -> Result<ByteCodeOffset, D::Error>
186    where
187        D: serde::Deserializer<'de>,
188    {
189        use serde::Deserialize;
190
191        let offset = OffsetSerde::deserialize(deserializer)?;
192        let offset = match offset {
193            OffsetSerde::HexStr(felt) => felt,
194            OffsetSerde::Decimal(decimal) => Felt::from_u64(decimal),
195        };
196        Ok(ByteCodeOffset(offset))
197    }
198}
199
200impl<T> Dummy<T> for SelectorAndOffset {
201    fn dummy_with_rng<R: rand::prelude::Rng + ?Sized>(_: &T, rng: &mut R) -> Self {
202        Self {
203            selector: Faker.fake_with_rng(rng),
204            offset: ByteCodeOffset(Felt::from_u64(rng.gen())),
205        }
206    }
207}
208
209/// Descriptor of an entry point in a Sierra class.
210#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, Dummy)]
211#[serde(deny_unknown_fields)]
212pub struct SelectorAndFunctionIndex {
213    pub selector: EntryPoint,
214    pub function_idx: u64,
215}
216
217impl SerializedSierraDefinition {
218    pub fn from_vec(bytes: Vec<u8>) -> Self {
219        Self(Bytes::from_owner(bytes))
220    }
221
222    pub fn from_slice(bytes: &[u8]) -> Self {
223        Self(Bytes::copy_from_slice(bytes))
224    }
225
226    pub fn into_vec(self) -> Vec<u8> {
227        self.0.into()
228    }
229
230    pub fn as_slice(&self) -> &[u8] {
231        &self.0
232    }
233}
234
235impl From<Bytes> for SerializedSierraDefinition {
236    fn from(bytes: Bytes) -> Self {
237        Self(bytes)
238    }
239}
240
241impl SerializedCasmDefinition {
242    pub fn from_vec(bytes: Vec<u8>) -> Self {
243        Self(Bytes::from_owner(bytes))
244    }
245
246    pub fn from_slice(bytes: &[u8]) -> Self {
247        Self(Bytes::copy_from_slice(bytes))
248    }
249
250    pub fn into_vec(self) -> Vec<u8> {
251        self.0.into()
252    }
253
254    pub fn as_slice(&self) -> &[u8] {
255        &self.0
256    }
257}
258
259impl SerializedCairoDefinition {
260    pub fn from_vec(bytes: Vec<u8>) -> Self {
261        Self(Bytes::from_owner(bytes))
262    }
263
264    pub fn from_slice(bytes: &[u8]) -> Self {
265        Self(Bytes::copy_from_slice(bytes))
266    }
267
268    pub fn into_vec(self) -> Vec<u8> {
269        self.0.into()
270    }
271
272    pub fn as_slice(&self) -> &[u8] {
273        &self.0
274    }
275}
276
277impl From<Bytes> for SerializedCairoDefinition {
278    fn from(bytes: Bytes) -> Self {
279        Self(bytes)
280    }
281}
282
283impl SerializedOpaqueClassDefinition {
284    pub fn from_vec(bytes: Vec<u8>) -> Self {
285        Self(Bytes::from_owner(bytes))
286    }
287
288    pub fn from_slice(bytes: &[u8]) -> Self {
289        Self(Bytes::copy_from_slice(bytes))
290    }
291
292    pub fn into_vec(self) -> Vec<u8> {
293        self.0.into()
294    }
295
296    pub fn as_slice(&self) -> &[u8] {
297        &self.0
298    }
299
300    pub fn into_inner(self) -> Bytes {
301        self.0
302    }
303}
304
305/// We can use `From` because this is always safe.
306impl From<SerializedSierraDefinition> for SerializedOpaqueClassDefinition {
307    fn from(d: SerializedSierraDefinition) -> Self {
308        Self::from_vec(d.into_vec())
309    }
310}
311
312/// We can use `From` because this is always safe.
313impl From<SerializedCairoDefinition> for SerializedOpaqueClassDefinition {
314    fn from(d: SerializedCairoDefinition) -> Self {
315        Self::from_vec(d.into_vec())
316    }
317}
318
319impl<T> Dummy<T> for SerializedSierraDefinition {
320    fn dummy_with_rng<R: rand::prelude::Rng + ?Sized>(_: &T, rng: &mut R) -> Self {
321        Self(Bytes::from(Faker.fake_with_rng::<Vec<u8>, R>(rng)))
322    }
323}
324
325impl<T> Dummy<T> for SerializedCasmDefinition {
326    fn dummy_with_rng<R: rand::prelude::Rng + ?Sized>(_: &T, rng: &mut R) -> Self {
327        Self(Bytes::from(Faker.fake_with_rng::<Vec<u8>, R>(rng)))
328    }
329}
330
331impl<T> Dummy<T> for SerializedCairoDefinition {
332    fn dummy_with_rng<R: rand::prelude::Rng + ?Sized>(_: &T, rng: &mut R) -> Self {
333        Self(Bytes::from(Faker.fake_with_rng::<Vec<u8>, R>(rng)))
334    }
335}
336
337impl<T> Dummy<T> for SerializedOpaqueClassDefinition {
338    fn dummy_with_rng<R: rand::prelude::Rng + ?Sized>(_: &T, rng: &mut R) -> Self {
339        Self(Bytes::from(Faker.fake_with_rng::<Vec<u8>, R>(rng)))
340    }
341}