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 #[allow(clippy::needless_range_loop)]
117 for index in 0..32 {
118 let position = offset + index;
119 if position >= self.data.len() {
120 break;
121 }
122
123 ret[index] = self.data[position];
124 }
125
126 H256(ret)
127 }
128
129 pub fn set(
135 &mut self,
136 offset: usize,
137 value: &[u8],
138 target_size: Option<usize>,
139 ) -> Result<(), ExitFatal> {
140 let target_size = target_size.unwrap_or(value.len());
141 if target_size == 0 {
142 return Ok(());
143 }
144
145 if offset
146 .checked_add(target_size)
147 .map_or(true, |pos| pos > self.limit)
148 {
149 return Err(ExitFatal::NotSupported);
150 }
151
152 if self.data.len() < offset + target_size {
153 self.data.resize(offset + target_size, 0);
154 }
155
156 if target_size > value.len() {
157 self.data[offset..((value.len()) + offset)].clone_from_slice(value);
158 for index in (value.len())..target_size {
159 self.data[offset + index] = 0;
160 }
161 } else {
162 self.data[offset..(target_size + offset)].clone_from_slice(&value[..target_size]);
163 }
164
165 Ok(())
166 }
167
168 pub fn copy(
176 &mut self,
177 src_offset: usize,
178 dst_offset: usize,
179 length: usize,
180 ) -> Result<(), ExitFatal> {
181 if length == 0 {
183 return Ok(());
184 }
185
186 let offset = core::cmp::max(src_offset, dst_offset);
188 let offset_length = offset
189 .checked_add(length)
190 .ok_or_else(|| ExitFatal::Other(Cow::from("OverflowOnCopy")))?;
191 if offset_length > self.limit {
192 return Err(ExitFatal::Other(Cow::from("OutOfGasOnCopy")));
193 }
194
195 if self.data.len() < offset_length {
197 self.data.resize(offset_length, 0);
198 }
199
200 self.data
201 .copy_within(src_offset..src_offset + length, dst_offset);
202 Ok(())
203 }
204
205 pub fn copy_large(
210 &mut self,
211 memory_offset: usize,
212 data_offset: U256,
213 len: usize,
214 data: &[u8],
215 ) -> Result<(), ExitFatal> {
216 if len == 0 {
222 return Ok(());
223 }
224
225 #[allow(clippy::as_conversions)]
226 let data = data_offset
227 .checked_add(len.into())
228 .map_or(&[] as &[u8], |end| {
229 if end > USIZE_MAX {
230 &[]
231 } else {
232 let data_offset = data_offset.as_usize();
233 let end = end.as_usize();
234
235 if data_offset > data.len() {
236 &[]
237 } else {
238 &data[data_offset..min(end, data.len())]
239 }
240 }
241 });
242
243 self.set(memory_offset, data, Some(len))
244 }
245}
246
247#[inline]
249fn next_multiple_of_32(x: usize) -> Option<usize> {
250 let r = x.bitand(31).not().wrapping_add(1).bitand(31);
251 x.checked_add(r)
252}
253
254#[cfg(test)]
255mod tests {
256 use super::next_multiple_of_32;
257
258 #[test]
259 fn test_next_multiple_of_32() {
260 for i in 0..32 {
262 let x = i * 32;
263 assert_eq!(Some(x), next_multiple_of_32(x));
264 }
265
266 for x in 0..1024 {
268 if x % 32 == 0 {
269 continue;
270 }
271 let next_multiple = x + 32 - (x % 32);
272 assert_eq!(Some(next_multiple), next_multiple_of_32(x));
273 }
274
275 let last_multiple_of_32 = usize::MAX & !31;
277 for i in 0..63 {
278 let x = usize::MAX - i;
279 if x > last_multiple_of_32 {
280 assert_eq!(None, next_multiple_of_32(x));
281 } else {
282 assert_eq!(Some(last_multiple_of_32), next_multiple_of_32(x));
283 }
284 }
285 }
286}