revm_interpreter/interpreter/
stack.rs
1use crate::{
2 primitives::{B256, U256},
3 InstructionResult,
4};
5use core::{fmt, ptr};
6use std::vec::Vec;
7
8pub const STACK_LIMIT: usize = 1024;
10
11#[derive(Debug, PartialEq, Eq, Hash)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize))]
14pub struct Stack {
15 data: Vec<U256>,
17}
18
19impl fmt::Display for Stack {
20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 f.write_str("[")?;
22 for (i, x) in self.data.iter().enumerate() {
23 if i > 0 {
24 f.write_str(", ")?;
25 }
26 write!(f, "{x}")?;
27 }
28 f.write_str("]")
29 }
30}
31
32impl Default for Stack {
33 #[inline]
34 fn default() -> Self {
35 Self::new()
36 }
37}
38
39impl Stack {
40 #[inline]
42 pub fn new() -> Self {
43 Self {
44 data: Vec::with_capacity(STACK_LIMIT),
46 }
47 }
48
49 #[inline]
51 pub fn len(&self) -> usize {
52 self.data.len()
53 }
54
55 #[inline]
57 pub fn is_empty(&self) -> bool {
58 self.data.is_empty()
59 }
60
61 #[inline]
63 pub fn data(&self) -> &Vec<U256> {
64 &self.data
65 }
66
67 #[inline]
69 pub fn data_mut(&mut self) -> &mut Vec<U256> {
70 &mut self.data
71 }
72
73 #[inline]
75 pub fn into_data(self) -> Vec<U256> {
76 self.data
77 }
78
79 #[inline]
82 pub fn pop(&mut self) -> Result<U256, InstructionResult> {
83 self.data.pop().ok_or(InstructionResult::StackUnderflow)
84 }
85
86 #[inline]
92 pub unsafe fn pop_unsafe(&mut self) -> U256 {
93 self.data.pop().unwrap_unchecked()
94 }
95
96 #[inline]
102 pub unsafe fn top_unsafe(&mut self) -> &mut U256 {
103 let len = self.data.len();
104 self.data.get_unchecked_mut(len - 1)
105 }
106
107 #[inline]
113 pub unsafe fn pop_top_unsafe(&mut self) -> (U256, &mut U256) {
114 let pop = self.pop_unsafe();
115 let top = self.top_unsafe();
116 (pop, top)
117 }
118
119 #[inline]
125 pub unsafe fn pop2_unsafe(&mut self) -> (U256, U256) {
126 let pop1 = self.pop_unsafe();
127 let pop2 = self.pop_unsafe();
128 (pop1, pop2)
129 }
130
131 #[inline]
137 pub unsafe fn pop2_top_unsafe(&mut self) -> (U256, U256, &mut U256) {
138 let pop1 = self.pop_unsafe();
139 let pop2 = self.pop_unsafe();
140 let top = self.top_unsafe();
141
142 (pop1, pop2, top)
143 }
144
145 #[inline]
151 pub unsafe fn pop3_unsafe(&mut self) -> (U256, U256, U256) {
152 let pop1 = self.pop_unsafe();
153 let pop2 = self.pop_unsafe();
154 let pop3 = self.pop_unsafe();
155
156 (pop1, pop2, pop3)
157 }
158
159 #[inline]
165 pub unsafe fn pop4_unsafe(&mut self) -> (U256, U256, U256, U256) {
166 let pop1 = self.pop_unsafe();
167 let pop2 = self.pop_unsafe();
168 let pop3 = self.pop_unsafe();
169 let pop4 = self.pop_unsafe();
170
171 (pop1, pop2, pop3, pop4)
172 }
173
174 #[inline]
180 pub unsafe fn pop5_unsafe(&mut self) -> (U256, U256, U256, U256, U256) {
181 let pop1 = self.pop_unsafe();
182 let pop2 = self.pop_unsafe();
183 let pop3 = self.pop_unsafe();
184 let pop4 = self.pop_unsafe();
185 let pop5 = self.pop_unsafe();
186
187 (pop1, pop2, pop3, pop4, pop5)
188 }
189
190 #[inline]
193 pub fn push_b256(&mut self, value: B256) -> Result<(), InstructionResult> {
194 self.push(value.into())
195 }
196
197 #[inline]
202 pub fn push(&mut self, value: U256) -> Result<(), InstructionResult> {
203 assume!(self.data.capacity() == STACK_LIMIT);
205 if self.data.len() == STACK_LIMIT {
206 return Err(InstructionResult::StackOverflow);
207 }
208 self.data.push(value);
209 Ok(())
210 }
211
212 #[inline]
216 pub fn peek(&self, no_from_top: usize) -> Result<U256, InstructionResult> {
217 if self.data.len() > no_from_top {
218 Ok(self.data[self.data.len() - no_from_top - 1])
219 } else {
220 Err(InstructionResult::StackUnderflow)
221 }
222 }
223
224 #[inline]
230 #[cfg_attr(debug_assertions, track_caller)]
231 pub fn dup(&mut self, n: usize) -> Result<(), InstructionResult> {
232 assume!(n > 0, "attempted to dup 0");
233 let len = self.data.len();
234 if len < n {
235 Err(InstructionResult::StackUnderflow)
236 } else if len + 1 > STACK_LIMIT {
237 Err(InstructionResult::StackOverflow)
238 } else {
239 unsafe {
241 let ptr = self.data.as_mut_ptr().add(len);
242 ptr::copy_nonoverlapping(ptr.sub(n), ptr, 1);
243 self.data.set_len(len + 1);
244 }
245 Ok(())
246 }
247 }
248
249 #[inline(always)]
255 #[cfg_attr(debug_assertions, track_caller)]
256 pub fn swap(&mut self, n: usize) -> Result<(), InstructionResult> {
257 self.exchange(0, n)
258 }
259
260 #[inline]
268 #[cfg_attr(debug_assertions, track_caller)]
269 pub fn exchange(&mut self, n: usize, m: usize) -> Result<(), InstructionResult> {
270 assume!(m > 0, "overlapping exchange");
271 let len = self.data.len();
272 let n_m_index = n + m;
273 if n_m_index >= len {
274 return Err(InstructionResult::StackUnderflow);
275 }
276 unsafe {
278 let top = self.data.as_mut_ptr().add(len - 1);
283 core::ptr::swap_nonoverlapping(top.sub(n), top.sub(n_m_index), 1);
284 }
285 Ok(())
286 }
287
288 #[inline]
291 pub fn push_slice(&mut self, slice: &[u8]) -> Result<(), InstructionResult> {
292 if slice.is_empty() {
293 return Ok(());
294 }
295
296 let n_words = (slice.len() + 31) / 32;
297 let new_len = self.data.len() + n_words;
298 if new_len > STACK_LIMIT {
299 return Err(InstructionResult::StackOverflow);
300 }
301
302 unsafe {
304 let dst = self.data.as_mut_ptr().add(self.data.len()).cast::<u64>();
305 self.data.set_len(new_len);
306
307 let mut i = 0;
308
309 let words = slice.chunks_exact(32);
311 let partial_last_word = words.remainder();
312 for word in words {
313 for l in word.rchunks_exact(8) {
316 dst.add(i).write(u64::from_be_bytes(l.try_into().unwrap()));
317 i += 1;
318 }
319 }
320
321 if partial_last_word.is_empty() {
322 return Ok(());
323 }
324
325 let limbs = partial_last_word.rchunks_exact(8);
327 let partial_last_limb = limbs.remainder();
328 for l in limbs {
329 dst.add(i).write(u64::from_be_bytes(l.try_into().unwrap()));
330 i += 1;
331 }
332
333 if !partial_last_limb.is_empty() {
335 let mut tmp = [0u8; 8];
336 tmp[8 - partial_last_limb.len()..].copy_from_slice(partial_last_limb);
337 dst.add(i).write(u64::from_be_bytes(tmp));
338 i += 1;
339 }
340
341 debug_assert_eq!((i + 3) / 4, n_words, "wrote too much");
342
343 let m = i % 4; if m != 0 {
346 dst.add(i).write_bytes(0, 4 - m);
347 }
348 }
349
350 Ok(())
351 }
352
353 #[inline]
357 pub fn set(&mut self, no_from_top: usize, val: U256) -> Result<(), InstructionResult> {
358 if self.data.len() > no_from_top {
359 let len = self.data.len();
360 self.data[len - no_from_top - 1] = val;
361 Ok(())
362 } else {
363 Err(InstructionResult::StackUnderflow)
364 }
365 }
366}
367
368#[cfg(feature = "serde")]
369impl<'de> serde::Deserialize<'de> for Stack {
370 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
371 where
372 D: serde::Deserializer<'de>,
373 {
374 let mut data = Vec::<U256>::deserialize(deserializer)?;
375 if data.len() > STACK_LIMIT {
376 return Err(serde::de::Error::custom(std::format!(
377 "stack size exceeds limit: {} > {}",
378 data.len(),
379 STACK_LIMIT
380 )));
381 }
382 data.reserve(STACK_LIMIT - data.len());
383 Ok(Self { data })
384 }
385}
386
387#[cfg(test)]
388mod tests {
389 use super::*;
390
391 fn run(f: impl FnOnce(&mut Stack)) {
392 let mut stack = Stack::new();
393 unsafe {
395 stack.data.set_len(STACK_LIMIT);
396 stack.data.fill(U256::MAX);
397 stack.data.set_len(0);
398 }
399 f(&mut stack);
400 }
401
402 #[test]
403 fn push_slices() {
404 run(|stack| {
406 stack.push_slice(b"").unwrap();
407 assert_eq!(stack.data, []);
408 });
409
410 run(|stack| {
412 stack.push_slice(&[42]).unwrap();
413 assert_eq!(stack.data, [U256::from(42)]);
414 });
415
416 let n = 0x1111_2222_3333_4444_5555_6666_7777_8888_u128;
417 run(|stack| {
418 stack.push_slice(&n.to_be_bytes()).unwrap();
419 assert_eq!(stack.data, [U256::from(n)]);
420 });
421
422 run(|stack| {
424 let b = [U256::from(n).to_be_bytes::<32>(); 2].concat();
425 stack.push_slice(&b).unwrap();
426 assert_eq!(stack.data, [U256::from(n); 2]);
427 });
428
429 run(|stack| {
430 let b = [&[0; 32][..], &[42u8]].concat();
431 stack.push_slice(&b).unwrap();
432 assert_eq!(stack.data, [U256::ZERO, U256::from(42)]);
433 });
434
435 run(|stack| {
436 let b = [&[0; 32][..], &n.to_be_bytes()].concat();
437 stack.push_slice(&b).unwrap();
438 assert_eq!(stack.data, [U256::ZERO, U256::from(n)]);
439 });
440
441 run(|stack| {
442 let b = [&[0; 64][..], &n.to_be_bytes()].concat();
443 stack.push_slice(&b).unwrap();
444 assert_eq!(stack.data, [U256::ZERO, U256::ZERO, U256::from(n)]);
445 });
446 }
447}