1use fuel_storage::{
4 StorageAsRef,
5 StorageInspect,
6 StorageMutate,
7 StorageRead,
8 StorageSize,
9 StorageWrite,
10};
11use fuel_tx::{
12 ConsensusParameters,
13 Contract,
14 StorageSlot,
15};
16use fuel_types::{
17 AssetId,
18 BlockHeight,
19 Bytes32,
20 ContractId,
21 Word,
22};
23
24use crate::{
25 prelude::{
26 InterpreterError,
27 RuntimeError,
28 },
29 storage::{
30 ContractsAssets,
31 ContractsRawCode,
32 ContractsState,
33 ContractsStateData,
34 UploadedBytecode,
35 UploadedBytecodes,
36 },
37};
38use alloc::{
39 borrow::Cow,
40 vec::Vec,
41};
42use core::ops::{
43 Deref,
44 DerefMut,
45};
46
47use super::blob_data::BlobData;
48
49pub trait InterpreterStorage:
52 StorageWrite<ContractsRawCode, Error = Self::DataError>
53 + StorageSize<ContractsRawCode, Error = Self::DataError>
54 + StorageRead<ContractsRawCode, Error = Self::DataError>
55 + StorageWrite<ContractsState, Error = Self::DataError>
56 + StorageSize<ContractsState, Error = Self::DataError>
57 + StorageRead<ContractsState, Error = Self::DataError>
58 + StorageMutate<UploadedBytecodes, Error = Self::DataError>
59 + StorageWrite<BlobData, Error = Self::DataError>
60 + StorageSize<BlobData, Error = Self::DataError>
61 + StorageRead<BlobData, Error = Self::DataError>
62 + ContractsAssetsStorage<Error = Self::DataError>
63{
64 type DataError: Into<InterpreterError<Self::DataError>>
66 + Into<RuntimeError<Self::DataError>>
67 + core::fmt::Debug;
68
69 fn block_height(&self) -> Result<BlockHeight, Self::DataError>;
72
73 fn consensus_parameters_version(&self) -> Result<u32, Self::DataError>;
75
76 fn state_transition_version(&self) -> Result<u32, Self::DataError>;
79
80 fn timestamp(&self, height: BlockHeight) -> Result<Word, Self::DataError>;
87
88 fn block_hash(&self, block_height: BlockHeight) -> Result<Bytes32, Self::DataError>;
90
91 fn coinbase(&self) -> Result<ContractId, Self::DataError>;
93
94 fn set_consensus_parameters(
98 &mut self,
99 version: u32,
100 consensus_parameters: &ConsensusParameters,
101 ) -> Result<Option<ConsensusParameters>, Self::DataError>;
102
103 fn contains_state_transition_bytecode_root(
106 &self,
107 root: &Bytes32,
108 ) -> Result<bool, Self::DataError> {
109 let bytecode = self.storage::<UploadedBytecodes>().get(root)?;
110
111 if let Some(cow) = bytecode {
112 if let UploadedBytecode::Completed(_) = cow.as_ref() {
113 Ok(true)
114 } else {
115 Ok(false)
116 }
117 } else {
118 Ok(false)
119 }
120 }
121
122 fn set_state_transition_bytecode(
126 &mut self,
127 version: u32,
128 hash: &Bytes32,
129 ) -> Result<Option<Bytes32>, Self::DataError>;
130
131 fn deploy_contract_with_id(
133 &mut self,
134 slots: &[StorageSlot],
135 contract: &Contract,
136 id: &ContractId,
137 ) -> Result<(), Self::DataError> {
138 self.storage_contract_insert(id, contract)?;
139
140 slots.iter().try_for_each(|s| {
142 self.contract_state_insert(id, s.key(), s.value().as_ref())?;
143 Ok(())
144 })?;
145 Ok(())
146 }
147
148 fn storage_contract(
151 &self,
152 id: &ContractId,
153 ) -> Result<Option<Cow<'_, Contract>>, Self::DataError> {
154 StorageInspect::<ContractsRawCode>::get(self, id)
155 }
156
157 fn storage_contract_size(
160 &self,
161 id: &ContractId,
162 ) -> Result<Option<usize>, Self::DataError> {
163 StorageSize::<ContractsRawCode>::size_of_value(self, id)
164 }
165
166 fn storage_contract_insert(
170 &mut self,
171 id: &ContractId,
172 contract: &Contract,
173 ) -> Result<(), Self::DataError> {
174 StorageMutate::<ContractsRawCode>::insert(self, id, contract.as_ref())
175 }
176
177 fn storage_contract_exists(&self, id: &ContractId) -> Result<bool, Self::DataError> {
179 self.storage::<ContractsRawCode>().contains_key(id)
180 }
181
182 fn contract_state(
184 &self,
185 id: &ContractId,
186 key: &Bytes32,
187 ) -> Result<Option<Cow<'_, ContractsStateData>>, Self::DataError> {
188 StorageInspect::<ContractsState>::get(self, &(id, key).into())
189 }
190
191 fn contract_state_insert(
193 &mut self,
194 contract: &ContractId,
195 key: &Bytes32,
196 value: &[u8],
197 ) -> Result<(), Self::DataError> {
198 StorageWrite::<ContractsState>::write_bytes(
199 self,
200 &(contract, key).into(),
201 value,
202 )?;
203 Ok(())
204 }
205
206 fn contract_state_replace(
208 &mut self,
209 contract: &ContractId,
210 key: &Bytes32,
211 value: &[u8],
212 ) -> Result<Option<Vec<u8>>, Self::DataError> {
213 let (_, prev) = StorageWrite::<ContractsState>::replace_bytes(
214 self,
215 &(contract, key).into(),
216 value,
217 )?;
218 Ok(prev)
219 }
220
221 fn contract_state_range(
225 &self,
226 id: &ContractId,
227 start_key: &Bytes32,
228 range: usize,
229 ) -> Result<Vec<Option<Cow<ContractsStateData>>>, Self::DataError>;
230
231 fn contract_state_insert_range<'a, I>(
234 &mut self,
235 contract: &ContractId,
236 start_key: &Bytes32,
237 values: I,
238 ) -> Result<usize, Self::DataError>
239 where
240 I: Iterator<Item = &'a [u8]>;
241
242 fn contract_state_remove_range(
245 &mut self,
246 contract: &ContractId,
247 start_key: &Bytes32,
248 range: usize,
249 ) -> Result<Option<()>, Self::DataError>;
250}
251
252pub trait ContractsAssetsStorage: StorageMutate<ContractsAssets> {
254 fn contract_asset_id_balance(
256 &self,
257 id: &ContractId,
258 asset_id: &AssetId,
259 ) -> Result<Option<Word>, Self::Error> {
260 let balance = self
261 .storage::<ContractsAssets>()
262 .get(&(id, asset_id).into())?
263 .map(Cow::into_owned);
264
265 Ok(balance)
266 }
267
268 fn contract_asset_id_balance_insert(
270 &mut self,
271 contract: &ContractId,
272 asset_id: &AssetId,
273 value: Word,
274 ) -> Result<(), Self::Error> {
275 StorageMutate::<ContractsAssets>::insert(
276 self,
277 &(contract, asset_id).into(),
278 &value,
279 )
280 }
281
282 fn contract_asset_id_balance_replace(
285 &mut self,
286 contract: &ContractId,
287 asset_id: &AssetId,
288 value: Word,
289 ) -> Result<Option<Word>, Self::Error> {
290 StorageMutate::<ContractsAssets>::replace(
291 self,
292 &(contract, asset_id).into(),
293 &value,
294 )
295 }
296}
297
298impl<S> ContractsAssetsStorage for &mut S where S: ContractsAssetsStorage {}
299
300impl<S> InterpreterStorage for &mut S
301where
302 S: InterpreterStorage,
303{
304 type DataError = <S as InterpreterStorage>::DataError;
305
306 fn block_height(&self) -> Result<BlockHeight, Self::DataError> {
307 <S as InterpreterStorage>::block_height(self.deref())
308 }
309
310 fn consensus_parameters_version(&self) -> Result<u32, Self::DataError> {
311 <S as InterpreterStorage>::consensus_parameters_version(self.deref())
312 }
313
314 fn state_transition_version(&self) -> Result<u32, Self::DataError> {
315 <S as InterpreterStorage>::state_transition_version(self.deref())
316 }
317
318 fn timestamp(&self, height: BlockHeight) -> Result<Word, Self::DataError> {
319 <S as InterpreterStorage>::timestamp(self.deref(), height)
320 }
321
322 fn block_hash(&self, block_height: BlockHeight) -> Result<Bytes32, Self::DataError> {
323 <S as InterpreterStorage>::block_hash(self.deref(), block_height)
324 }
325
326 fn coinbase(&self) -> Result<ContractId, Self::DataError> {
327 <S as InterpreterStorage>::coinbase(self.deref())
328 }
329
330 fn set_consensus_parameters(
331 &mut self,
332 version: u32,
333 consensus_parameters: &ConsensusParameters,
334 ) -> Result<Option<ConsensusParameters>, Self::DataError> {
335 <S as InterpreterStorage>::set_consensus_parameters(
336 self.deref_mut(),
337 version,
338 consensus_parameters,
339 )
340 }
341
342 fn set_state_transition_bytecode(
343 &mut self,
344 version: u32,
345 hash: &Bytes32,
346 ) -> Result<Option<Bytes32>, Self::DataError> {
347 <S as InterpreterStorage>::set_state_transition_bytecode(
348 self.deref_mut(),
349 version,
350 hash,
351 )
352 }
353
354 fn storage_contract_size(
355 &self,
356 id: &ContractId,
357 ) -> Result<Option<usize>, Self::DataError> {
358 <S as InterpreterStorage>::storage_contract_size(self.deref(), id)
359 }
360
361 fn contract_state_range(
362 &self,
363 id: &ContractId,
364 start_key: &Bytes32,
365 range: usize,
366 ) -> Result<Vec<Option<Cow<ContractsStateData>>>, Self::DataError> {
367 <S as InterpreterStorage>::contract_state_range(
368 self.deref(),
369 id,
370 start_key,
371 range,
372 )
373 }
374
375 fn contract_state_insert_range<'a, I>(
376 &mut self,
377 contract: &ContractId,
378 start_key: &Bytes32,
379 values: I,
380 ) -> Result<usize, Self::DataError>
381 where
382 I: Iterator<Item = &'a [u8]>,
383 {
384 <S as InterpreterStorage>::contract_state_insert_range(
385 self.deref_mut(),
386 contract,
387 start_key,
388 values,
389 )
390 }
391
392 fn contract_state_remove_range(
393 &mut self,
394 contract: &ContractId,
395 start_key: &Bytes32,
396 range: usize,
397 ) -> Result<Option<()>, Self::DataError> {
398 <S as InterpreterStorage>::contract_state_remove_range(
399 self.deref_mut(),
400 contract,
401 start_key,
402 range,
403 )
404 }
405}