aurora_evm/core/
memory.rs1use super::prelude::*;
2use super::utils::USIZE_MAX;
3use crate::{ExitError, ExitFatal};
4use core::cmp::min;
5use core::ops::{BitAnd, Not};
6use primitive_types::{H256, U256};
7
8#[derive(Clone, Debug)]
11pub struct Memory {
12 data: Vec<u8>,
14 effective_len: usize,
16 limit: usize,
18}
19
20impl Memory {
21 #[must_use]
23 pub const fn new(limit: usize) -> Self {
24 Self {
25 data: Vec::new(),
26 effective_len: 0,
27 limit,
28 }
29 }
30
31 #[must_use]
33 pub const fn limit(&self) -> usize {
34 self.limit
35 }
36
37 #[must_use]
39 pub fn len(&self) -> usize {
40 self.data.len()
41 }
42
43 #[must_use]
45 pub const fn effective_len(&self) -> usize {
46 self.effective_len
47 }
48
49 #[must_use]
51 pub fn is_empty(&self) -> bool {
52 self.len() == 0
53 }
54
55 #[must_use]
57 pub const fn data(&self) -> &Vec<u8> {
58 &self.data
59 }
60
61 pub fn resize_offset(&mut self, offset: usize, len: usize) -> Result<(), ExitError> {
67 if len == 0 {
68 return Ok(());
69 }
70
71 offset
72 .checked_add(len)
73 .map_or(Err(ExitError::InvalidRange), |end| self.resize_end(end))
74 }
75
76 pub fn resize_end(&mut self, end: usize) -> Result<(), ExitError> {
81 if end > self.effective_len {
82 let new_end = next_multiple_of_32(end).ok_or(ExitError::InvalidRange)?;
83 self.effective_len = new_end;
84 }
85
86 Ok(())
87 }
88
89 #[must_use]
96 pub fn get(&self, mut offset: usize, size: usize) -> Vec<u8> {
97 if offset > self.data.len() {
98 offset = self.data.len();
99 }
100
101 let mut end = offset + size;
102 if end > self.data.len() {
103 end = self.data.len();
104 }
105
106 let mut ret = self.data[offset..end].to_vec();
107 ret.resize(size, 0);
108 ret
109 }
110
111 #[must_use]
113 pub fn get_h256(&self, offset: usize) -> H256 {
114 let mut ret = [0; 32];
115
116 let data_len = self.data.len();
117 if offset >= data_len {
118 return H256(ret);
119 }
120 let available_bytes = data_len - offset;
121 let count = 32.min(available_bytes);
122 ret[..count].copy_from_slice(&self.data[offset..offset + count]);
123
124 H256(ret)
125 }
126
127 pub fn set(
133 &mut self,
134 offset: usize,
135 value: &[u8],
136 target_size: usize,
137 ) -> Result<(), ExitFatal> {
138 if target_size == 0 {
139 return Ok(());
140 }
141
142 let end_offset = match offset.checked_add(target_size) {
143 Some(pos) if pos <= self.limit => pos,
144 _ => return Err(ExitFatal::NotSupported),
145 };
146
147 if self.data.len() < end_offset {
148 self.data.resize(end_offset, 0);
149 }
150
151 let copy_len = min(value.len(), target_size);
152 let dest_slice = &mut self.data[offset..end_offset];
153 if copy_len > 0 {
154 dest_slice[..copy_len].copy_from_slice(&value[..copy_len]);
155 }
156
157 if target_size > copy_len {
158 dest_slice[copy_len..].fill(0);
159 }
160
161 Ok(())
162 }
163
164 pub fn copy(
172 &mut self,
173 src_offset: usize,
174 dst_offset: usize,
175 length: usize,
176 ) -> Result<(), ExitFatal> {
177 if length == 0 {
179 return Ok(());
180 }
181
182 let offset = core::cmp::max(src_offset, dst_offset);
184 let offset_length = offset
185 .checked_add(length)
186 .ok_or_else(|| ExitFatal::Other(Cow::from("OverflowOnCopy")))?;
187 if offset_length > self.limit {
188 return Err(ExitFatal::Other(Cow::from("OutOfGasOnCopy")));
189 }
190
191 if self.data.len() < offset_length {
193 self.data.resize(offset_length, 0);
194 }
195
196 self.data
197 .copy_within(src_offset..src_offset + length, dst_offset);
198 Ok(())
199 }
200
201 pub fn copy_data(
212 &mut self,
213 memory_offset: usize,
214 data_offset: U256,
215 length: usize,
216 data: &[u8],
217 ) -> Result<(), ExitFatal> {
218 if length == 0 {
220 return Ok(());
221 }
222
223 let dest_end_offset = match memory_offset.checked_add(length) {
225 Some(pos) if pos <= self.limit => pos,
226 _ => return Err(ExitFatal::NotSupported), };
228
229 if self.data.len() < dest_end_offset {
232 self.data.resize(dest_end_offset, 0);
233 }
234
235 let dest_slice = &mut self.data[memory_offset..dest_end_offset];
239
240 if data_offset > USIZE_MAX {
242 dest_slice.fill(0);
243 return Ok(());
244 }
245 let data_offset = data_offset.as_usize();
246 if data_offset > data.len() {
247 dest_slice.fill(0);
248 return Ok(());
249 }
250 let actual_len = data.len() - data_offset;
252 let copy_len = min(actual_len, length);
254 if copy_len > 0 {
256 dest_slice[..copy_len].copy_from_slice(&data[data_offset..data_offset + copy_len]);
257 }
258 if length > copy_len {
259 dest_slice[copy_len..].fill(0);
260 }
261 Ok(())
262 }
263}
264
265#[inline]
267fn next_multiple_of_32(x: usize) -> Option<usize> {
268 let r = x.bitand(31).not().wrapping_add(1).bitand(31);
269 x.checked_add(r)
270}
271
272#[cfg(test)]
273mod tests {
274 use super::next_multiple_of_32;
275
276 #[test]
277 fn test_next_multiple_of_32() {
278 for i in 0..32 {
280 let x = i * 32;
281 assert_eq!(Some(x), next_multiple_of_32(x));
282 }
283
284 for x in 0..1024 {
286 if x % 32 == 0 {
287 continue;
288 }
289 let next_multiple = x + 32 - (x % 32);
290 assert_eq!(Some(next_multiple), next_multiple_of_32(x));
291 }
292
293 let last_multiple_of_32 = usize::MAX & !31;
295 for i in 0..63 {
296 let x = usize::MAX - i;
297 if x > last_multiple_of_32 {
298 assert_eq!(None, next_multiple_of_32(x));
299 } else {
300 assert_eq!(Some(last_multiple_of_32), next_multiple_of_32(x));
301 }
302 }
303 }
304}