cairo_lang_sierra/extensions/modules/starknet/
storage.rs

1use num_bigint::BigInt;
2
3use super::syscalls::SyscallGenericLibfunc;
4use crate::extensions::consts::{ConstGenLibfunc, WrapConstGenLibfunc};
5use crate::extensions::felt252::Felt252Type;
6use crate::extensions::int::unsigned::{Uint8Type, Uint32Type, Uint64Type};
7use crate::extensions::lib_func::{
8    DeferredOutputKind, LibfuncSignature, OutputVarInfo, ParamSignature, SierraApChange,
9    SignatureSpecializationContext,
10};
11use crate::extensions::range_check::RangeCheckType;
12use crate::extensions::try_from_felt252::TryFromFelt252;
13use crate::extensions::utils::reinterpret_cast_signature;
14use crate::extensions::{
15    NamedType, NoGenericArgsGenericLibfunc, NoGenericArgsGenericType, OutputVarReferenceInfo,
16    SpecializationError,
17};
18use crate::ids::GenericTypeId;
19
20/// Type for Starknet storage base address, a value in the range [0, 2 ** 251 - 256).
21#[derive(Default)]
22pub struct StorageBaseAddressType {}
23impl NoGenericArgsGenericType for StorageBaseAddressType {
24    const ID: GenericTypeId = GenericTypeId::new_inline("StorageBaseAddress");
25    const STORABLE: bool = true;
26    const DUPLICATABLE: bool = true;
27    const DROPPABLE: bool = true;
28    const ZERO_SIZED: bool = false;
29}
30
31/// Libfunc for creating a constant storage base address.
32#[derive(Default)]
33pub struct StorageBaseAddressConstLibfuncWrapped {}
34impl ConstGenLibfunc for StorageBaseAddressConstLibfuncWrapped {
35    const STR_ID: &'static str = ("storage_base_address_const");
36    const GENERIC_TYPE_ID: GenericTypeId = <StorageBaseAddressType as NoGenericArgsGenericType>::ID;
37
38    fn bound() -> BigInt {
39        BigInt::from(2).pow(251) - 256
40    }
41}
42
43pub type StorageBaseAddressConstLibfunc =
44    WrapConstGenLibfunc<StorageBaseAddressConstLibfuncWrapped>;
45
46/// Type for Starknet storage base address, a value in the range [0, 2 ** 251).
47#[derive(Default)]
48pub struct StorageAddressType {}
49impl NoGenericArgsGenericType for StorageAddressType {
50    const ID: GenericTypeId = GenericTypeId::new_inline("StorageAddress");
51    const STORABLE: bool = true;
52    const DUPLICATABLE: bool = true;
53    const DROPPABLE: bool = true;
54    const ZERO_SIZED: bool = false;
55}
56
57/// Libfunc for converting a StorageAddress into a felt252.
58#[derive(Default)]
59pub struct StorageAddressToFelt252Libfunc {}
60impl NoGenericArgsGenericLibfunc for StorageAddressToFelt252Libfunc {
61    const STR_ID: &'static str = "storage_address_to_felt252";
62
63    fn specialize_signature(
64        &self,
65        context: &dyn SignatureSpecializationContext,
66    ) -> Result<LibfuncSignature, SpecializationError> {
67        Ok(reinterpret_cast_signature(
68            context.get_concrete_type(StorageAddressType::id(), &[])?,
69            context.get_concrete_type(Felt252Type::id(), &[])?,
70        ))
71    }
72}
73
74/// Libfunc for attempting to convert a felt252 into a storage address.
75#[derive(Default)]
76pub struct StorageAddressTryFromFelt252Trait;
77impl TryFromFelt252 for StorageAddressTryFromFelt252Trait {
78    const STR_ID: &'static str = "storage_address_try_from_felt252";
79    const GENERIC_TYPE_ID: GenericTypeId = <StorageAddressType as NoGenericArgsGenericType>::ID;
80}
81
82/// Libfunc for converting a base address into a storage address.
83#[derive(Default)]
84pub struct StorageAddressFromBaseLibfunc {}
85impl NoGenericArgsGenericLibfunc for StorageAddressFromBaseLibfunc {
86    const STR_ID: &'static str = "storage_address_from_base";
87
88    fn specialize_signature(
89        &self,
90        context: &dyn SignatureSpecializationContext,
91    ) -> Result<LibfuncSignature, SpecializationError> {
92        Ok(reinterpret_cast_signature(
93            context.get_concrete_type(StorageBaseAddressType::id(), &[])?,
94            context.get_concrete_type(StorageAddressType::id(), &[])?,
95        ))
96    }
97}
98
99/// Libfunc for converting a base address and offset into a storage address.
100#[derive(Default)]
101pub struct StorageAddressFromBaseAndOffsetLibfunc {}
102impl NoGenericArgsGenericLibfunc for StorageAddressFromBaseAndOffsetLibfunc {
103    const STR_ID: &'static str = "storage_address_from_base_and_offset";
104
105    fn specialize_signature(
106        &self,
107        context: &dyn SignatureSpecializationContext,
108    ) -> Result<LibfuncSignature, SpecializationError> {
109        Ok(LibfuncSignature::new_non_branch_ex(
110            vec![
111                ParamSignature::new(context.get_concrete_type(StorageBaseAddressType::id(), &[])?),
112                ParamSignature::new(context.get_concrete_type(Uint8Type::id(), &[])?)
113                    .with_allow_const(),
114            ],
115            vec![OutputVarInfo {
116                ty: context.get_concrete_type(StorageAddressType::id(), &[])?,
117                ref_info: OutputVarReferenceInfo::Deferred(DeferredOutputKind::Generic),
118            }],
119            SierraApChange::Known { new_vars_only: true },
120        ))
121    }
122}
123
124/// Libfunc for converting a felt252 into a storage base address.
125#[derive(Default)]
126pub struct StorageBaseAddressFromFelt252Libfunc {}
127impl NoGenericArgsGenericLibfunc for StorageBaseAddressFromFelt252Libfunc {
128    const STR_ID: &'static str = "storage_base_address_from_felt252";
129
130    fn specialize_signature(
131        &self,
132        context: &dyn SignatureSpecializationContext,
133    ) -> Result<LibfuncSignature, SpecializationError> {
134        let range_check_ty = context.get_concrete_type(RangeCheckType::id(), &[])?;
135        Ok(LibfuncSignature::new_non_branch_ex(
136            vec![
137                ParamSignature::new(range_check_ty.clone()).with_allow_add_const(),
138                ParamSignature::new(context.get_concrete_type(Felt252Type::id(), &[])?),
139            ],
140            vec![OutputVarInfo::new_builtin(range_check_ty, 0), OutputVarInfo {
141                ty: context.get_concrete_type(StorageBaseAddressType::id(), &[])?,
142                ref_info: OutputVarReferenceInfo::NewTempVar { idx: 0 },
143            }],
144            SierraApChange::Known { new_vars_only: false },
145        ))
146    }
147}
148
149/// Libfunc for a storage read system call.
150#[derive(Default)]
151pub struct StorageReadLibfunc {}
152impl SyscallGenericLibfunc for StorageReadLibfunc {
153    const STR_ID: &'static str = "storage_read_syscall";
154
155    fn input_tys(
156        context: &dyn SignatureSpecializationContext,
157    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
158        Ok(vec![
159            // Address domain.
160            context.get_concrete_type(Uint32Type::id(), &[])?,
161            // Storage key.
162            context.get_concrete_type(StorageAddressType::id(), &[])?,
163        ])
164    }
165
166    fn success_output_tys(
167        context: &dyn SignatureSpecializationContext,
168    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
169        Ok(vec![context.get_concrete_type(Felt252Type::id(), &[])?])
170    }
171}
172
173/// Libfunc for a storage write system call.
174#[derive(Default)]
175pub struct StorageWriteLibfunc {}
176impl SyscallGenericLibfunc for StorageWriteLibfunc {
177    const STR_ID: &'static str = "storage_write_syscall";
178
179    fn input_tys(
180        context: &dyn SignatureSpecializationContext,
181    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
182        Ok(vec![
183            // Address domain
184            context.get_concrete_type(Uint32Type::id(), &[])?,
185            // Storage key
186            context.get_concrete_type(StorageAddressType::id(), &[])?,
187            // Value
188            context.get_concrete_type(Felt252Type::id(), &[])?,
189        ])
190    }
191
192    fn success_output_tys(
193        _context: &dyn SignatureSpecializationContext,
194    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
195        Ok(vec![])
196    }
197}
198
199/// Libfunc for a get block hash system call.
200#[derive(Default)]
201pub struct GetBlockHashLibfunc {}
202impl SyscallGenericLibfunc for GetBlockHashLibfunc {
203    const STR_ID: &'static str = "get_block_hash_syscall";
204
205    fn input_tys(
206        context: &dyn SignatureSpecializationContext,
207    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
208        Ok(vec![
209            // Block number.
210            context.get_concrete_type(Uint64Type::id(), &[])?,
211        ])
212    }
213
214    fn success_output_tys(
215        context: &dyn SignatureSpecializationContext,
216    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
217        Ok(vec![
218            // Block hash.
219            context.get_concrete_type(Felt252Type::id(), &[])?,
220        ])
221    }
222}