rtvm_interpreter/interpreter/
stack.rs1use crate::{
2 primitives::{B256, U256},
3 InstructionResult,
4};
5use core::fmt;
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]
226 pub fn dup(&mut self, n: usize) -> Result<(), InstructionResult> {
227 let len = self.data.len();
228 if len < n {
229 Err(InstructionResult::StackUnderflow)
230 } else if len + 1 > STACK_LIMIT {
231 Err(InstructionResult::StackOverflow)
232 } else {
233 unsafe {
235 self.data.set_len(len + 1);
236 }
237 self.data[len] = self.data[len - n];
238 Ok(())
239 }
240 }
241
242 #[inline]
244 pub fn swap(&mut self, n: usize) -> Result<(), InstructionResult> {
245 let len = self.data.len();
246 if n >= len {
247 return Err(InstructionResult::StackUnderflow);
248 }
249 let last_index = len - 1;
250 self.data.swap(last_index, last_index - n);
251 Ok(())
252 }
253
254 #[inline]
257 pub fn exchange(&mut self, n: usize, m: usize) -> Result<(), InstructionResult> {
258 let len = self.data.len();
259 let n_m_index = n + m;
260 if n_m_index >= len {
261 return Err(InstructionResult::StackUnderflow);
262 }
263 let last_index = len - 1;
264 self.data.swap(last_index - n, last_index - n_m_index);
265 Ok(())
266 }
267
268 #[inline]
271 pub fn push_slice(&mut self, slice: &[u8]) -> Result<(), InstructionResult> {
272 if slice.is_empty() {
273 return Ok(());
274 }
275
276 let n_words = (slice.len() + 31) / 32;
277 let new_len = self.data.len() + n_words;
278 if new_len > STACK_LIMIT {
279 return Err(InstructionResult::StackOverflow);
280 }
281
282 unsafe {
284 let dst = self.data.as_mut_ptr().add(self.data.len()).cast::<u64>();
285 self.data.set_len(new_len);
286
287 let mut i = 0;
288
289 let words = slice.chunks_exact(32);
291 let partial_last_word = words.remainder();
292 for word in words {
293 for l in word.rchunks_exact(8) {
296 dst.add(i).write(u64::from_be_bytes(l.try_into().unwrap()));
297 i += 1;
298 }
299 }
300
301 if partial_last_word.is_empty() {
302 return Ok(());
303 }
304
305 let limbs = partial_last_word.rchunks_exact(8);
307 let partial_last_limb = limbs.remainder();
308 for l in limbs {
309 dst.add(i).write(u64::from_be_bytes(l.try_into().unwrap()));
310 i += 1;
311 }
312
313 if !partial_last_limb.is_empty() {
315 let mut tmp = [0u8; 8];
316 tmp[8 - partial_last_limb.len()..].copy_from_slice(partial_last_limb);
317 dst.add(i).write(u64::from_be_bytes(tmp));
318 i += 1;
319 }
320
321 debug_assert_eq!((i + 3) / 4, n_words, "wrote too much");
322
323 let m = i % 4; if m != 0 {
326 dst.add(i).write_bytes(0, 4 - m);
327 }
328 }
329
330 Ok(())
331 }
332
333 #[inline]
337 pub fn set(&mut self, no_from_top: usize, val: U256) -> Result<(), InstructionResult> {
338 if self.data.len() > no_from_top {
339 let len = self.data.len();
340 self.data[len - no_from_top - 1] = val;
341 Ok(())
342 } else {
343 Err(InstructionResult::StackUnderflow)
344 }
345 }
346}
347
348#[cfg(feature = "serde")]
349impl<'de> serde::Deserialize<'de> for Stack {
350 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
351 where
352 D: serde::Deserializer<'de>,
353 {
354 let mut data = Vec::<U256>::deserialize(deserializer)?;
355 if data.len() > STACK_LIMIT {
356 return Err(serde::de::Error::custom(std::format!(
357 "stack size exceeds limit: {} > {}",
358 data.len(),
359 STACK_LIMIT
360 )));
361 }
362 data.reserve(STACK_LIMIT - data.len());
363 Ok(Self { data })
364 }
365}
366
367#[cfg(test)]
368mod tests {
369 use super::*;
370
371 fn run(f: impl FnOnce(&mut Stack)) {
372 let mut stack = Stack::new();
373 unsafe {
375 stack.data.set_len(STACK_LIMIT);
376 stack.data.fill(U256::MAX);
377 stack.data.set_len(0);
378 }
379 f(&mut stack);
380 }
381
382 #[test]
383 fn push_slices() {
384 run(|stack| {
386 stack.push_slice(b"").unwrap();
387 assert_eq!(stack.data, []);
388 });
389
390 run(|stack| {
392 stack.push_slice(&[42]).unwrap();
393 assert_eq!(stack.data, [U256::from(42)]);
394 });
395
396 let n = 0x1111_2222_3333_4444_5555_6666_7777_8888_u128;
397 run(|stack| {
398 stack.push_slice(&n.to_be_bytes()).unwrap();
399 assert_eq!(stack.data, [U256::from(n)]);
400 });
401
402 run(|stack| {
404 let b = [U256::from(n).to_be_bytes::<32>(); 2].concat();
405 stack.push_slice(&b).unwrap();
406 assert_eq!(stack.data, [U256::from(n); 2]);
407 });
408
409 run(|stack| {
410 let b = [&[0; 32][..], &[42u8]].concat();
411 stack.push_slice(&b).unwrap();
412 assert_eq!(stack.data, [U256::ZERO, U256::from(42)]);
413 });
414
415 run(|stack| {
416 let b = [&[0; 32][..], &n.to_be_bytes()].concat();
417 stack.push_slice(&b).unwrap();
418 assert_eq!(stack.data, [U256::ZERO, U256::from(n)]);
419 });
420
421 run(|stack| {
422 let b = [&[0; 64][..], &n.to_be_bytes()].concat();
423 stack.push_slice(&b).unwrap();
424 assert_eq!(stack.data, [U256::ZERO, U256::ZERO, U256::from(n)]);
425 });
426 }
427}