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 StorageWrite::<ContractsState>::replace_bytes(
214 self,
215 &(contract, key).into(),
216 value,
217 )
218 }
219
220 fn contract_state_range(
224 &self,
225 id: &ContractId,
226 start_key: &Bytes32,
227 range: usize,
228 ) -> Result<Vec<Option<Cow<ContractsStateData>>>, Self::DataError>;
229
230 fn contract_state_insert_range<'a, I>(
233 &mut self,
234 contract: &ContractId,
235 start_key: &Bytes32,
236 values: I,
237 ) -> Result<usize, Self::DataError>
238 where
239 I: Iterator<Item = &'a [u8]>;
240
241 fn contract_state_remove_range(
244 &mut self,
245 contract: &ContractId,
246 start_key: &Bytes32,
247 range: usize,
248 ) -> Result<Option<()>, Self::DataError>;
249}
250
251pub trait ContractsAssetsStorage: StorageMutate<ContractsAssets> {
253 fn contract_asset_id_balance(
255 &self,
256 id: &ContractId,
257 asset_id: &AssetId,
258 ) -> Result<Option<Word>, Self::Error> {
259 let balance = self
260 .storage::<ContractsAssets>()
261 .get(&(id, asset_id).into())?
262 .map(Cow::into_owned);
263
264 Ok(balance)
265 }
266
267 fn contract_asset_id_balance_insert(
269 &mut self,
270 contract: &ContractId,
271 asset_id: &AssetId,
272 value: Word,
273 ) -> Result<(), Self::Error> {
274 StorageMutate::<ContractsAssets>::insert(
275 self,
276 &(contract, asset_id).into(),
277 &value,
278 )
279 }
280
281 fn contract_asset_id_balance_replace(
284 &mut self,
285 contract: &ContractId,
286 asset_id: &AssetId,
287 value: Word,
288 ) -> Result<Option<Word>, Self::Error> {
289 StorageMutate::<ContractsAssets>::replace(
290 self,
291 &(contract, asset_id).into(),
292 &value,
293 )
294 }
295}
296
297impl<S> ContractsAssetsStorage for &mut S where S: ContractsAssetsStorage {}
298
299impl<S> InterpreterStorage for &mut S
300where
301 S: InterpreterStorage,
302{
303 type DataError = <S as InterpreterStorage>::DataError;
304
305 fn block_height(&self) -> Result<BlockHeight, Self::DataError> {
306 <S as InterpreterStorage>::block_height(self.deref())
307 }
308
309 fn consensus_parameters_version(&self) -> Result<u32, Self::DataError> {
310 <S as InterpreterStorage>::consensus_parameters_version(self.deref())
311 }
312
313 fn state_transition_version(&self) -> Result<u32, Self::DataError> {
314 <S as InterpreterStorage>::state_transition_version(self.deref())
315 }
316
317 fn timestamp(&self, height: BlockHeight) -> Result<Word, Self::DataError> {
318 <S as InterpreterStorage>::timestamp(self.deref(), height)
319 }
320
321 fn block_hash(&self, block_height: BlockHeight) -> Result<Bytes32, Self::DataError> {
322 <S as InterpreterStorage>::block_hash(self.deref(), block_height)
323 }
324
325 fn coinbase(&self) -> Result<ContractId, Self::DataError> {
326 <S as InterpreterStorage>::coinbase(self.deref())
327 }
328
329 fn set_consensus_parameters(
330 &mut self,
331 version: u32,
332 consensus_parameters: &ConsensusParameters,
333 ) -> Result<Option<ConsensusParameters>, Self::DataError> {
334 <S as InterpreterStorage>::set_consensus_parameters(
335 self.deref_mut(),
336 version,
337 consensus_parameters,
338 )
339 }
340
341 fn set_state_transition_bytecode(
342 &mut self,
343 version: u32,
344 hash: &Bytes32,
345 ) -> Result<Option<Bytes32>, Self::DataError> {
346 <S as InterpreterStorage>::set_state_transition_bytecode(
347 self.deref_mut(),
348 version,
349 hash,
350 )
351 }
352
353 fn storage_contract_size(
354 &self,
355 id: &ContractId,
356 ) -> Result<Option<usize>, Self::DataError> {
357 <S as InterpreterStorage>::storage_contract_size(self.deref(), id)
358 }
359
360 fn contract_state_range(
361 &self,
362 id: &ContractId,
363 start_key: &Bytes32,
364 range: usize,
365 ) -> Result<Vec<Option<Cow<ContractsStateData>>>, Self::DataError> {
366 <S as InterpreterStorage>::contract_state_range(
367 self.deref(),
368 id,
369 start_key,
370 range,
371 )
372 }
373
374 fn contract_state_insert_range<'a, I>(
375 &mut self,
376 contract: &ContractId,
377 start_key: &Bytes32,
378 values: I,
379 ) -> Result<usize, Self::DataError>
380 where
381 I: Iterator<Item = &'a [u8]>,
382 {
383 <S as InterpreterStorage>::contract_state_insert_range(
384 self.deref_mut(),
385 contract,
386 start_key,
387 values,
388 )
389 }
390
391 fn contract_state_remove_range(
392 &mut self,
393 contract: &ContractId,
394 start_key: &Bytes32,
395 range: usize,
396 ) -> Result<Option<()>, Self::DataError> {
397 <S as InterpreterStorage>::contract_state_remove_range(
398 self.deref_mut(),
399 contract,
400 start_key,
401 range,
402 )
403 }
404}