Skip to main content

revmc_codegen/tests/
resume.rs

1use super::{DEF_SPEC, with_evm_context};
2use crate::{Backend, EvmCompiler, TEST_SUSPEND};
3use revm_bytecode::opcode as op;
4use revm_interpreter::InstructionResult;
5use revm_primitives::{U256, hardfork::SpecId};
6
7matrix_tests!(legacy = |compiler| run(compiler, TEST, DEF_SPEC));
8
9#[rustfmt::skip]
10const TEST: &[u8] = &[
11    // 0
12    op::PUSH1, 0x42,
13    TEST_SUSPEND,
14
15    // 1
16    op::PUSH1, 0x69,
17    TEST_SUSPEND,
18
19    // 2
20    op::ADD,
21    TEST_SUSPEND,
22
23    // 3
24    op::STOP,
25];
26
27fn run<B: Backend>(compiler: &mut EvmCompiler<B>, code: &[u8], spec_id: SpecId) {
28    let f = unsafe { compiler.jit("resume", code, spec_id) }.unwrap();
29
30    with_evm_context(code, spec_id, |ecx, stack, stack_len| {
31        assert_eq!(ecx.resume_at.get(), 0);
32
33        // Suspension returns `InstructionResult::Stop` with `resume_at` set to the next
34        // resume point. The `resume_at` assertions below verify that suspension occurred
35        // (as opposed to reaching an actual STOP opcode).
36
37        // op::PUSH1, 0x42,
38        let r = unsafe { f.call(stack, stack_len, ecx) };
39        assert_eq!(r, InstructionResult::Stop);
40        assert_eq!(*stack_len, 1);
41        assert_eq!(unsafe { stack.as_slice(*stack_len) }[0].to_u256(), U256::from(0x42));
42        let resume_1 = ecx.resume_at;
43        assert_eq!(resume_1.get(), 1);
44
45        // op::PUSH1, 0x69,
46        let r = unsafe { f.call(stack, stack_len, ecx) };
47        assert_eq!(r, InstructionResult::Stop);
48        assert_eq!(*stack_len, 2);
49        assert_eq!(unsafe { stack.as_slice(*stack_len) }[0].to_u256(), U256::from(0x42));
50        assert_eq!(unsafe { stack.as_slice(*stack_len) }[1].to_u256(), U256::from(0x69));
51        let resume_2 = ecx.resume_at;
52        assert_eq!(resume_2.get(), 2);
53
54        // op::ADD,
55        let r = unsafe { f.call(stack, stack_len, ecx) };
56        assert_eq!(r, InstructionResult::Stop);
57        assert_eq!(*stack_len, 1);
58        assert_eq!(unsafe { stack.as_slice(*stack_len) }[0].to_u256(), U256::from(0x42 + 0x69));
59        let resume_3 = ecx.resume_at;
60        assert_eq!(resume_3.get(), 3);
61
62        // stop
63        let r = unsafe { f.call(stack, stack_len, ecx) };
64        assert_eq!(r, InstructionResult::Stop);
65        assert_eq!(*stack_len, 1);
66        assert_eq!(unsafe { stack.as_slice(*stack_len) }[0].to_u256(), U256::from(0x42 + 0x69));
67        assert_eq!(ecx.resume_at, resume_3);
68
69        // op::ADD,
70        ecx.resume_at = resume_2;
71        let r = unsafe { f.call(stack, stack_len, ecx) };
72        assert_eq!(r, InstructionResult::StackUnderflow);
73        assert_eq!(*stack_len, 1);
74        assert_eq!(unsafe { stack.as_slice(*stack_len) }[0].to_u256(), U256::from(0x42 + 0x69));
75        assert_eq!(ecx.resume_at, resume_2);
76
77        stack.set(*stack_len, U256::from(2).into());
78        *stack_len += 1;
79
80        // op::ADD,
81        ecx.resume_at = resume_2;
82        let r = unsafe { f.call(stack, stack_len, ecx) };
83        assert_eq!(r, InstructionResult::Stop);
84        assert_eq!(*stack_len, 1);
85        assert_eq!(unsafe { stack.as_slice(*stack_len) }[0].to_u256(), U256::from(0x42 + 0x69 + 2));
86        assert_eq!(ecx.resume_at, resume_3);
87
88        // op::PUSH1, 0x69,
89        ecx.resume_at = resume_1;
90        let r = unsafe { f.call(stack, stack_len, ecx) };
91        assert_eq!(r, InstructionResult::Stop);
92        assert_eq!(*stack_len, 2);
93        assert_eq!(unsafe { stack.as_slice(*stack_len) }[0].to_u256(), U256::from(0x42 + 0x69 + 2));
94        assert_eq!(unsafe { stack.as_slice(*stack_len) }[1].to_u256(), U256::from(0x69));
95        assert_eq!(ecx.resume_at, resume_2);
96
97        // op::ADD,
98        let r = unsafe { f.call(stack, stack_len, ecx) };
99        assert_eq!(r, InstructionResult::Stop);
100        assert_eq!(*stack_len, 1);
101        assert_eq!(
102            unsafe { stack.as_slice(*stack_len) }[0].to_u256(),
103            U256::from(0x42 + 0x69 + 2 + 0x69)
104        );
105        assert_eq!(ecx.resume_at, resume_3);
106
107        // stop
108        let r = unsafe { f.call(stack, stack_len, ecx) };
109        assert_eq!(r, InstructionResult::Stop);
110        assert_eq!(*stack_len, 1);
111        assert_eq!(
112            unsafe { stack.as_slice(*stack_len) }[0].to_u256(),
113            U256::from(0x42 + 0x69 + 2 + 0x69)
114        );
115        assert_eq!(ecx.resume_at, resume_3);
116
117        // stop
118        let r = unsafe { f.call(stack, stack_len, ecx) };
119        assert_eq!(r, InstructionResult::Stop);
120        assert_eq!(*stack_len, 1);
121        assert_eq!(
122            unsafe { stack.as_slice(*stack_len) }[0].to_u256(),
123            U256::from(0x42 + 0x69 + 2 + 0x69)
124        );
125        assert_eq!(ecx.resume_at, resume_3);
126    });
127}