fuel_vm/storage/
predicate.rs

1//! The module contains storage requirements for the predicate execution.
2
3use crate::{
4    prelude::{
5        InterpreterError,
6        RuntimeError,
7    },
8    storage::InterpreterStorage,
9};
10use alloc::{
11    borrow::Cow,
12    string::String,
13    vec::Vec,
14};
15use core::fmt::Debug;
16
17use fuel_asm::Word;
18use fuel_storage::{
19    Mappable,
20    StorageInspect,
21    StorageMutate,
22    StorageRead,
23    StorageSize,
24    StorageWrite,
25};
26use fuel_tx::ConsensusParameters;
27use fuel_types::{
28    BlobId,
29    BlockHeight,
30    Bytes32,
31    ContractId,
32};
33
34use super::{
35    interpreter::ContractsAssetsStorage,
36    BlobData,
37    ContractsAssets,
38    ContractsRawCode,
39    ContractsState,
40    ContractsStateData,
41    UploadedBytecodes,
42};
43
44/// Create an empty predicate storage.
45pub fn empty_predicate_storage() -> PredicateStorage<EmptyStorage> {
46    PredicateStorage::new(EmptyStorage)
47}
48
49/// No-op storage used for predicate operations.
50///
51/// The storage implementations are expected to provide KV-like operations for contract
52/// operations. However, predicates, as defined in the protocol, cannot execute contract
53/// opcodes. This means its storage backend for predicate execution shouldn't provide any
54/// functionality. Unless the storage access is limited to immutable data and read-only.
55#[derive(Debug, Default)]
56pub struct PredicateStorage<D> {
57    storage: D,
58}
59
60impl<D> PredicateStorage<D> {
61    /// instantiate predicate storage with access to Blobs
62    pub fn new(storage: D) -> Self {
63        Self { storage }
64    }
65}
66
67/// Errors that happen when using predicate storage
68#[derive(Debug, Clone)]
69pub enum PredicateStorageError {
70    /// Storage operation is unavailable in predicate context.
71    UnsupportedStorageOperation,
72    /// An storage error occurred
73    StorageError(String),
74}
75
76impl From<PredicateStorageError> for InterpreterError<PredicateStorageError> {
77    fn from(val: PredicateStorageError) -> Self {
78        let rt: RuntimeError<PredicateStorageError> = val.into();
79        rt.into()
80    }
81}
82
83impl From<PredicateStorageError> for RuntimeError<PredicateStorageError> {
84    fn from(val: PredicateStorageError) -> Self {
85        RuntimeError::Storage(val)
86    }
87}
88
89/// Storage requirements for predicates.
90pub trait PredicateStorageRequirements
91where
92    Self: StorageRead<BlobData>,
93{
94    /// Converts the storage error to a string.
95    fn storage_error_to_string(error: Self::Error) -> String;
96}
97
98impl<D> PredicateStorageRequirements for &D
99where
100    D: PredicateStorageRequirements,
101{
102    fn storage_error_to_string(error: Self::Error) -> String {
103        D::storage_error_to_string(error)
104    }
105}
106
107/// The type that returns the predicate storage instance.
108pub trait PredicateStorageProvider: Sync {
109    /// The storage type.
110    type Storage: PredicateStorageRequirements + Send + Sync + 'static;
111
112    /// Returns the storage instance.
113    fn storage(&self) -> Self::Storage;
114}
115
116/// Empty storage.
117#[derive(Default, Debug, Clone, Copy)]
118pub struct EmptyStorage;
119
120impl StorageInspect<BlobData> for EmptyStorage {
121    type Error = PredicateStorageError;
122
123    fn get(
124        &self,
125        _: &BlobId,
126    ) -> Result<Option<Cow<<BlobData as Mappable>::OwnedValue>>, Self::Error> {
127        Err(Self::Error::UnsupportedStorageOperation)
128    }
129
130    fn contains_key(&self, _: &BlobId) -> Result<bool, Self::Error> {
131        Err(Self::Error::UnsupportedStorageOperation)
132    }
133}
134
135impl StorageSize<BlobData> for EmptyStorage {
136    fn size_of_value(&self, _: &BlobId) -> Result<Option<usize>, Self::Error> {
137        Err(Self::Error::UnsupportedStorageOperation)
138    }
139}
140
141impl StorageRead<BlobData> for EmptyStorage {
142    fn read(&self, _: &BlobId, _: usize, _: &mut [u8]) -> Result<bool, Self::Error> {
143        Err(Self::Error::UnsupportedStorageOperation)
144    }
145
146    fn read_alloc(&self, _: &BlobId) -> Result<Option<Vec<u8>>, Self::Error> {
147        Err(Self::Error::UnsupportedStorageOperation)
148    }
149}
150
151impl PredicateStorageRequirements for EmptyStorage {
152    fn storage_error_to_string(error: Self::Error) -> String {
153        alloc::format!("{:?}", error)
154    }
155}
156
157impl PredicateStorageProvider for EmptyStorage {
158    type Storage = Self;
159
160    fn storage(&self) -> Self::Storage {
161        *self
162    }
163}
164
165trait NoStorage {}
166
167impl NoStorage for ContractsState {}
168impl NoStorage for ContractsRawCode {}
169impl NoStorage for ContractsAssets {}
170impl NoStorage for UploadedBytecodes {}
171
172impl<Type, D> StorageInspect<Type> for PredicateStorage<D>
173where
174    Type: Mappable + NoStorage,
175{
176    type Error = PredicateStorageError;
177
178    fn get(
179        &self,
180        _key: &Type::Key,
181    ) -> Result<Option<Cow<'_, Type::OwnedValue>>, Self::Error> {
182        Err(Self::Error::UnsupportedStorageOperation)
183    }
184
185    fn contains_key(&self, _key: &Type::Key) -> Result<bool, Self::Error> {
186        Err(Self::Error::UnsupportedStorageOperation)
187    }
188}
189
190impl<D> StorageInspect<BlobData> for PredicateStorage<D>
191where
192    D: PredicateStorageRequirements,
193{
194    type Error = PredicateStorageError;
195
196    fn get(
197        &self,
198        key: &<BlobData as Mappable>::Key,
199    ) -> Result<Option<Cow<'_, <BlobData as Mappable>::OwnedValue>>, Self::Error> {
200        <D as StorageInspect<BlobData>>::get(&self.storage, key)
201            .map_err(|e| Self::Error::StorageError(D::storage_error_to_string(e)))
202    }
203
204    fn contains_key(
205        &self,
206        key: &<BlobData as Mappable>::Key,
207    ) -> Result<bool, Self::Error> {
208        <D as StorageInspect<BlobData>>::contains_key(&self.storage, key)
209            .map_err(|e| Self::Error::StorageError(D::storage_error_to_string(e)))
210    }
211}
212
213impl<Type, D> StorageMutate<Type> for PredicateStorage<D>
214where
215    Type: Mappable,
216    Self: StorageInspect<Type, Error = PredicateStorageError>,
217{
218    fn replace(
219        &mut self,
220        _key: &Type::Key,
221        _value: &Type::Value,
222    ) -> Result<Option<Type::OwnedValue>, Self::Error> {
223        Err(Self::Error::UnsupportedStorageOperation)
224    }
225
226    fn take(
227        &mut self,
228        _key: &Type::Key,
229    ) -> Result<Option<Type::OwnedValue>, Self::Error> {
230        Err(Self::Error::UnsupportedStorageOperation)
231    }
232}
233
234impl<D> StorageSize<ContractsRawCode> for PredicateStorage<D> {
235    fn size_of_value(&self, _key: &ContractId) -> Result<Option<usize>, Self::Error> {
236        Err(Self::Error::UnsupportedStorageOperation)
237    }
238}
239
240impl<D> StorageRead<ContractsRawCode> for PredicateStorage<D> {
241    fn read(
242        &self,
243        _key: &<ContractsRawCode as Mappable>::Key,
244        _offset: usize,
245        _buf: &mut [u8],
246    ) -> Result<bool, Self::Error> {
247        Err(Self::Error::UnsupportedStorageOperation)
248    }
249
250    fn read_alloc(
251        &self,
252        _key: &<ContractsRawCode as Mappable>::Key,
253    ) -> Result<Option<Vec<u8>>, Self::Error> {
254        Err(Self::Error::UnsupportedStorageOperation)
255    }
256}
257
258impl<D> StorageWrite<ContractsRawCode> for PredicateStorage<D> {
259    fn write_bytes(
260        &mut self,
261        _key: &<ContractsRawCode as Mappable>::Key,
262        _buf: &[u8],
263    ) -> Result<(), Self::Error> {
264        Err(Self::Error::UnsupportedStorageOperation)
265    }
266
267    fn replace_bytes(
268        &mut self,
269        _key: &<ContractsRawCode as Mappable>::Key,
270        _buf: &[u8],
271    ) -> Result<Option<Vec<u8>>, Self::Error> {
272        Err(Self::Error::UnsupportedStorageOperation)
273    }
274
275    fn take_bytes(
276        &mut self,
277        _key: &<ContractsRawCode as Mappable>::Key,
278    ) -> Result<Option<Vec<u8>>, Self::Error> {
279        Err(Self::Error::UnsupportedStorageOperation)
280    }
281}
282
283impl<D> StorageSize<ContractsState> for PredicateStorage<D> {
284    fn size_of_value(
285        &self,
286        _key: &<ContractsState as Mappable>::Key,
287    ) -> Result<Option<usize>, Self::Error> {
288        Err(Self::Error::UnsupportedStorageOperation)
289    }
290}
291
292impl<D> StorageRead<ContractsState> for PredicateStorage<D> {
293    fn read(
294        &self,
295        _key: &<ContractsState as Mappable>::Key,
296        _offset: usize,
297        _buf: &mut [u8],
298    ) -> Result<bool, Self::Error> {
299        Err(Self::Error::UnsupportedStorageOperation)
300    }
301
302    fn read_alloc(
303        &self,
304        _key: &<ContractsState as Mappable>::Key,
305    ) -> Result<Option<Vec<u8>>, Self::Error> {
306        Err(Self::Error::UnsupportedStorageOperation)
307    }
308}
309
310impl<D> StorageWrite<ContractsState> for PredicateStorage<D> {
311    fn write_bytes(
312        &mut self,
313        _key: &<ContractsState as Mappable>::Key,
314        _buf: &[u8],
315    ) -> Result<(), Self::Error> {
316        Err(Self::Error::UnsupportedStorageOperation)
317    }
318
319    fn replace_bytes(
320        &mut self,
321        _key: &<ContractsState as Mappable>::Key,
322        _buf: &[u8],
323    ) -> Result<Option<Vec<u8>>, Self::Error> {
324        Err(Self::Error::UnsupportedStorageOperation)
325    }
326
327    fn take_bytes(
328        &mut self,
329        _key: &<ContractsState as Mappable>::Key,
330    ) -> Result<Option<Vec<u8>>, Self::Error> {
331        Err(Self::Error::UnsupportedStorageOperation)
332    }
333}
334
335impl<D> StorageSize<BlobData> for PredicateStorage<D>
336where
337    D: PredicateStorageRequirements,
338{
339    fn size_of_value(
340        &self,
341        key: &<BlobData as Mappable>::Key,
342    ) -> Result<Option<usize>, Self::Error> {
343        StorageSize::<BlobData>::size_of_value(&self.storage, key)
344            .map_err(|e| Self::Error::StorageError(D::storage_error_to_string(e)))
345    }
346}
347
348impl<D> StorageRead<BlobData> for PredicateStorage<D>
349where
350    D: PredicateStorageRequirements,
351{
352    fn read(
353        &self,
354        key: &<BlobData as Mappable>::Key,
355        offset: usize,
356        buf: &mut [u8],
357    ) -> Result<bool, Self::Error> {
358        StorageRead::<BlobData>::read(&self.storage, key, offset, buf)
359            .map_err(|e| Self::Error::StorageError(D::storage_error_to_string(e)))
360    }
361
362    fn read_alloc(
363        &self,
364        key: &<BlobData as Mappable>::Key,
365    ) -> Result<Option<Vec<u8>>, Self::Error> {
366        StorageRead::<BlobData>::read_alloc(&self.storage, key)
367            .map_err(|e| Self::Error::StorageError(D::storage_error_to_string(e)))
368    }
369}
370
371impl<D> StorageWrite<BlobData> for PredicateStorage<D>
372where
373    D: PredicateStorageRequirements,
374{
375    fn write_bytes(
376        &mut self,
377        _key: &<BlobData as Mappable>::Key,
378        _buf: &[u8],
379    ) -> Result<(), Self::Error> {
380        Err(Self::Error::UnsupportedStorageOperation)
381    }
382
383    fn replace_bytes(
384        &mut self,
385        _key: &<BlobData as Mappable>::Key,
386        _buf: &[u8],
387    ) -> Result<Option<Vec<u8>>, Self::Error> {
388        Err(Self::Error::UnsupportedStorageOperation)
389    }
390
391    fn take_bytes(
392        &mut self,
393        _key: &<BlobData as Mappable>::Key,
394    ) -> Result<Option<Vec<u8>>, Self::Error> {
395        Err(Self::Error::UnsupportedStorageOperation)
396    }
397}
398
399impl<D> ContractsAssetsStorage for PredicateStorage<D> {}
400
401impl<D> InterpreterStorage for PredicateStorage<D>
402where
403    D: PredicateStorageRequirements,
404{
405    type DataError = PredicateStorageError;
406
407    fn block_height(&self) -> Result<BlockHeight, Self::DataError> {
408        Err(Self::DataError::UnsupportedStorageOperation)
409    }
410
411    fn consensus_parameters_version(&self) -> Result<u32, Self::DataError> {
412        Err(Self::DataError::UnsupportedStorageOperation)
413    }
414
415    fn state_transition_version(&self) -> Result<u32, Self::DataError> {
416        Err(Self::DataError::UnsupportedStorageOperation)
417    }
418
419    fn timestamp(&self, _height: BlockHeight) -> Result<Word, Self::DataError> {
420        Err(Self::DataError::UnsupportedStorageOperation)
421    }
422
423    fn block_hash(&self, _block_height: BlockHeight) -> Result<Bytes32, Self::DataError> {
424        Err(Self::DataError::UnsupportedStorageOperation)
425    }
426
427    fn coinbase(&self) -> Result<ContractId, Self::DataError> {
428        Err(Self::DataError::UnsupportedStorageOperation)
429    }
430
431    fn set_consensus_parameters(
432        &mut self,
433        _version: u32,
434        _consensus_parameters: &ConsensusParameters,
435    ) -> Result<Option<ConsensusParameters>, Self::DataError> {
436        Err(Self::DataError::UnsupportedStorageOperation)
437    }
438
439    fn set_state_transition_bytecode(
440        &mut self,
441        _version: u32,
442        _hash: &Bytes32,
443    ) -> Result<Option<Bytes32>, Self::DataError> {
444        Err(Self::DataError::UnsupportedStorageOperation)
445    }
446
447    fn contract_state_range(
448        &self,
449        _id: &ContractId,
450        _start_key: &Bytes32,
451        _range: usize,
452    ) -> Result<Vec<Option<Cow<ContractsStateData>>>, Self::DataError> {
453        Err(Self::DataError::UnsupportedStorageOperation)
454    }
455
456    fn contract_state_insert_range<'a, I>(
457        &mut self,
458        _: &ContractId,
459        _: &Bytes32,
460        _: I,
461    ) -> Result<usize, Self::DataError>
462    where
463        I: Iterator<Item = &'a [u8]>,
464    {
465        Err(Self::DataError::UnsupportedStorageOperation)
466    }
467
468    fn contract_state_remove_range(
469        &mut self,
470        _contract: &ContractId,
471        _start_key: &Bytes32,
472        _range: usize,
473    ) -> Result<Option<()>, Self::DataError> {
474        Err(Self::DataError::UnsupportedStorageOperation)
475    }
476}