fuel_vm/
storage.rs

1//! Storage backend implementations.
2
3use fuel_storage::Mappable;
4use fuel_tx::Contract;
5use fuel_types::{
6    Bytes32,
7    ContractId,
8};
9
10mod blob_data;
11mod contracts_assets;
12mod contracts_state;
13mod interpreter;
14#[cfg(feature = "test-helpers")]
15mod memory;
16pub mod predicate;
17
18pub use blob_data::{
19    BlobBytes,
20    BlobData,
21};
22pub use contracts_assets::{
23    ContractsAssetKey,
24    ContractsAssets,
25};
26pub use contracts_state::{
27    ContractsState,
28    ContractsStateData,
29    ContractsStateKey,
30};
31pub use interpreter::{
32    ContractsAssetsStorage,
33    InterpreterStorage,
34};
35#[cfg(feature = "test-helpers")]
36pub use memory::{
37    MemoryStorage,
38    MemoryStorageError,
39};
40
41#[cfg(feature = "alloc")]
42use alloc::vec::Vec;
43
44#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
45#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
46/// The uploaded bytecode can be in two states: fully uploaded or partially uploaded.
47pub enum UploadedBytecode {
48    /// The bytecode is partially uploaded.
49    Uncompleted {
50        /// The cumulative bytecode of `uploaded_subsections_number` parts.
51        bytecode: Vec<u8>,
52        /// The number of already included subsections of the bytecode.
53        uploaded_subsections_number: u16,
54    },
55    /// The bytecode is fully uploaded and ready to be used.
56    Completed(Vec<u8>),
57}
58
59/// The storage table for uploaded bytecode.
60pub struct UploadedBytecodes;
61
62impl Mappable for UploadedBytecodes {
63    /// The key is a Merkle root of the bytecode.
64    type Key = Self::OwnedKey;
65    type OwnedKey = Bytes32;
66    type OwnedValue = UploadedBytecode;
67    type Value = Self::OwnedValue;
68}
69
70/// The storage table for contract's raw byte code.
71pub struct ContractsRawCode;
72
73impl Mappable for ContractsRawCode {
74    type Key = Self::OwnedKey;
75    type OwnedKey = ContractId;
76    type OwnedValue = Contract;
77    type Value = [u8];
78}
79
80/// The macro defines a new type of double storage key. It is a merge of the two
81/// types into one general type that represents the storage key of some entity.
82///
83/// Both types are represented by one big array. It is done from the performance
84/// perspective to minimize the number of copies. The current code doesn't use
85/// consumed values and uses it in most cases as on big key(except tests, which
86/// require access to sub-keys). But in the future, we may change the layout of the
87/// fields based on the performance measurements/new business logic.
88#[macro_export]
89macro_rules! double_key {
90    (
91        $i:ident, $first:ident, $first_getter:ident, $second:ident, $second_getter:ident
92    ) => {
93        #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
94        /// The FuelVM storage double key.
95        pub struct $i([u8; { $first::LEN + $second::LEN }]);
96
97        impl Default for $i {
98            fn default() -> Self {
99                Self([0; { Self::second_end() }])
100            }
101        }
102
103        impl $i {
104            /// The length of the underlying array.
105            pub const LEN: usize = $first::LEN + $second::LEN;
106
107            /// Create a new instance of the double storage key from references.
108            pub fn new(first: &$first, second: &$second) -> Self {
109                let mut default = Self::default();
110                default.0[0..Self::first_end()].copy_from_slice(first.as_ref());
111                default.0[Self::first_end()..Self::second_end()]
112                    .copy_from_slice(second.as_ref());
113                default
114            }
115
116            /// Creates a new instance of double storage key from the array.
117            pub fn from_array(array: [u8; { $first::LEN + $second::LEN }]) -> Self {
118                Self(array)
119            }
120
121            /// Creates a new instance of double storage key from the slice.
122            pub fn from_slice(
123                slice: &[u8],
124            ) -> Result<Self, core::array::TryFromSliceError> {
125                Ok(Self(slice.try_into()?))
126            }
127
128            /// Returns the reference to the first sub-key.
129            pub fn $first_getter(&self) -> &$first {
130                $first::from_bytes_ref(
131                    (&self.0[0..Self::first_end()])
132                        .try_into()
133                        .expect("0..first_end() < first_end() + second_end()"),
134                )
135            }
136
137            /// Returns the reference to the second sub-key.
138            pub fn $second_getter(&self) -> &$second {
139                $second::from_bytes_ref(
140                    (&self.0[Self::first_end()..Self::second_end()])
141                        .try_into()
142                        .expect("first_end()..second_end() < first_end() + second_end()"),
143                )
144            }
145
146            const fn first_end() -> usize {
147                $first::LEN
148            }
149
150            const fn second_end() -> usize {
151                $first::LEN + $second::LEN
152            }
153        }
154
155        impl From<(&$first, &$second)> for $i {
156            fn from(pair: (&$first, &$second)) -> Self {
157                Self::new(pair.0, pair.1)
158            }
159        }
160
161        impl AsRef<[u8]> for $i {
162            fn as_ref(&self) -> &[u8] {
163                self.0.as_ref()
164            }
165        }
166
167        impl From<$i> for ($first, $second) {
168            fn from(key: $i) -> ($first, $second) {
169                let first = &key.0[0..$i::first_end()];
170                let second = &key.0[$i::first_end()..$i::second_end()];
171                let first = first.try_into().unwrap();
172                let second = second.try_into().unwrap();
173                (first, second)
174            }
175        }
176
177        impl From<$i> for [u8; { $first::LEN + $second::LEN }] {
178            fn from(key: $i) -> [u8; { $first::LEN + $second::LEN }] {
179                key.0
180            }
181        }
182
183        impl TryFrom<&[u8]> for $i {
184            type Error = core::array::TryFromSliceError;
185
186            fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
187                $i::from_slice(slice)
188            }
189        }
190
191        #[cfg(feature = "serde")]
192        impl serde::Serialize for $i {
193            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
194            where
195                S: serde::Serializer,
196            {
197                use serde_with::SerializeAs;
198                serde_with::Bytes::serialize_as(&self.0, serializer)
199            }
200        }
201
202        #[cfg(feature = "serde")]
203        impl<'a> serde::Deserialize<'a> for $i {
204            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
205            where
206                D: serde::Deserializer<'a>,
207            {
208                use serde_with::DeserializeAs;
209                let bytes: [u8; $i::LEN] =
210                    serde_with::Bytes::deserialize_as(deserializer)?;
211                Ok(Self(bytes))
212            }
213        }
214    };
215}