Skip to main content

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