fuel_vm/
storage.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
//! Storage backend implementations.

use fuel_storage::Mappable;
use fuel_tx::Contract;
use fuel_types::{
    Bytes32,
    ContractId,
};

mod blob_data;
mod contracts_assets;
mod contracts_state;
mod interpreter;
#[cfg(feature = "test-helpers")]
mod memory;
pub mod predicate;

pub use blob_data::{
    BlobBytes,
    BlobData,
};
pub use contracts_assets::{
    ContractsAssetKey,
    ContractsAssets,
};
pub use contracts_state::{
    ContractsState,
    ContractsStateData,
    ContractsStateKey,
};
pub use interpreter::{
    ContractsAssetsStorage,
    InterpreterStorage,
};
#[cfg(feature = "test-helpers")]
pub use memory::MemoryStorage;

#[cfg(feature = "alloc")]
use alloc::vec::Vec;

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// The uploaded bytecode can be in two states: fully uploaded or partially uploaded.
pub enum UploadedBytecode {
    /// The bytecode is partially uploaded.
    Uncompleted {
        /// The cumulative bytecode of `uploaded_subsections_number` parts.
        bytecode: Vec<u8>,
        /// The number of already included subsections of the bytecode.
        uploaded_subsections_number: u16,
    },
    /// The bytecode is fully uploaded and ready to be used.
    Completed(Vec<u8>),
}

/// The storage table for uploaded bytecode.
pub struct UploadedBytecodes;

impl Mappable for UploadedBytecodes {
    /// The key is a Merkle root of the bytecode.
    type Key = Self::OwnedKey;
    type OwnedKey = Bytes32;
    type OwnedValue = UploadedBytecode;
    type Value = Self::OwnedValue;
}

/// The storage table for contract's raw byte code.
pub struct ContractsRawCode;

impl Mappable for ContractsRawCode {
    type Key = Self::OwnedKey;
    type OwnedKey = ContractId;
    type OwnedValue = Contract;
    type Value = [u8];
}

/// The macro defines a new type of double storage key. It is a merge of the two
/// types into one general type that represents the storage key of some entity.
///
/// Both types are represented by one big array. It is done from the performance
/// perspective to minimize the number of copies. The current code doesn't use
/// consumed values and uses it in most cases as on big key(except tests, which
/// require access to sub-keys). But in the future, we may change the layout of the
/// fields based on the performance measurements/new business logic.
#[macro_export]
macro_rules! double_key {
    (
        $i:ident, $first:ident, $first_getter:ident, $second:ident, $second_getter:ident
    ) => {
        #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
        /// The FuelVM storage double key.
        pub struct $i([u8; { $first::LEN + $second::LEN }]);

        impl Default for $i {
            fn default() -> Self {
                Self([0; { Self::second_end() }])
            }
        }

        impl $i {
            /// The length of the underlying array.
            pub const LEN: usize = $first::LEN + $second::LEN;

            /// Create a new instance of the double storage key from references.
            pub fn new(first: &$first, second: &$second) -> Self {
                let mut default = Self::default();
                default.0[0..Self::first_end()].copy_from_slice(first.as_ref());
                default.0[Self::first_end()..Self::second_end()]
                    .copy_from_slice(second.as_ref());
                default
            }

            /// Creates a new instance of double storage key from the array.
            pub fn from_array(array: [u8; { $first::LEN + $second::LEN }]) -> Self {
                Self(array)
            }

            /// Creates a new instance of double storage key from the slice.
            pub fn from_slice(
                slice: &[u8],
            ) -> Result<Self, core::array::TryFromSliceError> {
                Ok(Self(slice.try_into()?))
            }

            /// Returns the reference to the first sub-key.
            pub fn $first_getter(&self) -> &$first {
                $first::from_bytes_ref(
                    (&self.0[0..Self::first_end()])
                        .try_into()
                        .expect("0..first_end() < first_end() + second_end()"),
                )
            }

            /// Returns the reference to the second sub-key.
            pub fn $second_getter(&self) -> &$second {
                $second::from_bytes_ref(
                    (&self.0[Self::first_end()..Self::second_end()])
                        .try_into()
                        .expect("first_end()..second_end() < first_end() + second_end()"),
                )
            }

            const fn first_end() -> usize {
                $first::LEN
            }

            const fn second_end() -> usize {
                $first::LEN + $second::LEN
            }
        }

        impl From<(&$first, &$second)> for $i {
            fn from(pair: (&$first, &$second)) -> Self {
                Self::new(pair.0, pair.1)
            }
        }

        impl AsRef<[u8]> for $i {
            fn as_ref(&self) -> &[u8] {
                self.0.as_ref()
            }
        }

        impl From<$i> for ($first, $second) {
            fn from(key: $i) -> ($first, $second) {
                let first = &key.0[0..$i::first_end()];
                let second = &key.0[$i::first_end()..$i::second_end()];
                let first = first.try_into().unwrap();
                let second = second.try_into().unwrap();
                (first, second)
            }
        }

        impl From<$i> for [u8; { $first::LEN + $second::LEN }] {
            fn from(key: $i) -> [u8; { $first::LEN + $second::LEN }] {
                key.0
            }
        }

        impl TryFrom<&[u8]> for $i {
            type Error = core::array::TryFromSliceError;

            fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
                $i::from_slice(slice)
            }
        }

        #[cfg(feature = "serde")]
        impl serde::Serialize for $i {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where
                S: serde::Serializer,
            {
                use serde_with::SerializeAs;
                serde_with::Bytes::serialize_as(&self.0, serializer)
            }
        }

        #[cfg(feature = "serde")]
        impl<'a> serde::Deserialize<'a> for $i {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: serde::Deserializer<'a>,
            {
                use serde_with::DeserializeAs;
                let bytes: [u8; $i::LEN] =
                    serde_with::Bytes::deserialize_as(deserializer)?;
                Ok(Self(bytes))
            }
        }
    };
}