1use crate::{
2 gas,
3 interpreter::Interpreter,
4 interpreter_types::{
5 EofCodeInfo, Immediates, InterpreterTypes, Jumps, LoopControl, MemoryTr, RuntimeFlag,
6 StackTr, SubRoutineStack,
7 },
8 Host, InstructionResult, InterpreterAction, InterpreterResult,
9};
10use primitives::{Bytes, U256};
11
12pub fn rjump<WIRE: InterpreterTypes, H: ?Sized>(
13 interpreter: &mut Interpreter<WIRE>,
14 _host: &mut H,
15) {
16 require_eof!(interpreter);
17 gas!(interpreter, gas::BASE);
18 let offset = interpreter.bytecode.read_i16() as isize;
19 interpreter.bytecode.relative_jump(offset + 2);
22}
23
24pub fn rjumpi<WIRE: InterpreterTypes, H: Host + ?Sized>(
25 interpreter: &mut Interpreter<WIRE>,
26 _host: &mut H,
27) {
28 require_eof!(interpreter);
29 gas!(interpreter, gas::CONDITION_JUMP_GAS);
30 popn!([condition], interpreter);
31 let mut offset = 2;
34 if !condition.is_zero() {
35 offset += interpreter.bytecode.read_i16() as isize;
36 }
37
38 interpreter.bytecode.relative_jump(offset);
39}
40
41pub fn rjumpv<WIRE: InterpreterTypes, H: Host + ?Sized>(
42 interpreter: &mut Interpreter<WIRE>,
43 _host: &mut H,
44) {
45 require_eof!(interpreter);
46 gas!(interpreter, gas::CONDITION_JUMP_GAS);
47 popn!([case], interpreter);
48 let case = as_isize_saturated!(case);
49
50 let max_index = interpreter.bytecode.read_u8() as isize;
51 let mut offset = (max_index + 1) * 2 + 1;
54
55 if case <= max_index {
56 offset += interpreter.bytecode.read_offset_i16(1 + case * 2) as isize;
57 }
58 interpreter.bytecode.relative_jump(offset);
59}
60
61pub fn jump<WIRE: InterpreterTypes, H: Host + ?Sized>(
62 interpreter: &mut Interpreter<WIRE>,
63 _host: &mut H,
64) {
65 gas!(interpreter, gas::MID);
66 popn!([target], interpreter);
67 jump_inner(interpreter, target);
68}
69
70pub fn jumpi<WIRE: InterpreterTypes, H: Host + ?Sized>(
71 interpreter: &mut Interpreter<WIRE>,
72 _host: &mut H,
73) {
74 gas!(interpreter, gas::HIGH);
75 popn!([target, cond], interpreter);
76
77 if !cond.is_zero() {
78 jump_inner(interpreter, target);
79 }
80}
81
82#[inline]
83fn jump_inner<WIRE: InterpreterTypes>(interpreter: &mut Interpreter<WIRE>, target: U256) {
84 let target = as_usize_or_fail!(interpreter, target, InstructionResult::InvalidJump);
85 if !interpreter.bytecode.is_valid_legacy_jump(target) {
86 interpreter
87 .control
88 .set_instruction_result(InstructionResult::InvalidJump);
89 return;
90 }
91 interpreter.bytecode.absolute_jump(target);
93}
94
95pub fn jumpdest_or_nop<WIRE: InterpreterTypes, H: Host + ?Sized>(
96 interpreter: &mut Interpreter<WIRE>,
97 _host: &mut H,
98) {
99 gas!(interpreter, gas::JUMPDEST);
100}
101
102pub fn callf<WIRE: InterpreterTypes, H: Host + ?Sized>(
103 interpreter: &mut Interpreter<WIRE>,
104 _host: &mut H,
105) {
106 require_eof!(interpreter);
107 gas!(interpreter, gas::LOW);
108
109 let idx = interpreter.bytecode.read_u16() as usize;
110 let Some(types) = interpreter.bytecode.code_info(idx) else {
112 panic!("Invalid EOF in execution, expecting correct intermediate in callf")
113 };
114
115 if interpreter.stack.len() + types.max_stack_increase as usize > 1024 {
118 interpreter
119 .control
120 .set_instruction_result(InstructionResult::StackOverflow);
121 return;
122 }
123
124 if !(interpreter
127 .sub_routine
128 .push(interpreter.bytecode.pc() + 2, idx))
129 {
130 interpreter
131 .control
132 .set_instruction_result(InstructionResult::SubRoutineStackOverflow);
133 return;
134 };
135 let pc = interpreter
136 .bytecode
137 .code_section_pc(idx)
138 .expect("Invalid code section index");
139 interpreter.bytecode.absolute_jump(pc);
140}
141
142pub fn retf<WIRE: InterpreterTypes, H: Host + ?Sized>(
143 interpreter: &mut Interpreter<WIRE>,
144 _host: &mut H,
145) {
146 require_eof!(interpreter);
147 gas!(interpreter, gas::RETF_GAS);
148
149 let Some(jump) = interpreter.sub_routine.pop() else {
150 panic!("Expected function frame")
151 };
152
153 interpreter.bytecode.absolute_jump(jump);
154}
155
156pub fn jumpf<WIRE: InterpreterTypes, H: Host + ?Sized>(
157 interpreter: &mut Interpreter<WIRE>,
158 _host: &mut H,
159) {
160 require_eof!(interpreter);
161 gas!(interpreter, gas::LOW);
162
163 let idx = interpreter.bytecode.read_u16() as usize;
164
165 let types = interpreter
167 .bytecode
168 .code_info(idx)
169 .expect("Invalid code section index");
170
171 if interpreter.stack.len() + types.max_stack_increase as usize > 1024 {
173 interpreter
174 .control
175 .set_instruction_result(InstructionResult::StackOverflow);
176 return;
177 }
178 interpreter.sub_routine.set_routine_idx(idx);
179 let pc = interpreter
180 .bytecode
181 .code_section_pc(idx)
182 .expect("Invalid code section index");
183 interpreter.bytecode.absolute_jump(pc);
184}
185
186pub fn pc<WIRE: InterpreterTypes, H: Host + ?Sized>(
187 interpreter: &mut Interpreter<WIRE>,
188 _host: &mut H,
189) {
190 gas!(interpreter, gas::BASE);
191 push!(interpreter, U256::from(interpreter.bytecode.pc() - 1));
193}
194
195#[inline]
196fn return_inner(
197 interpreter: &mut Interpreter<impl InterpreterTypes>,
198 instruction_result: InstructionResult,
199) {
200 popn!([offset, len], interpreter);
203 let len = as_usize_or_fail!(interpreter, len);
204 let mut output = Bytes::default();
206 if len != 0 {
207 let offset = as_usize_or_fail!(interpreter, offset);
208 resize_memory!(interpreter, offset, len);
209 output = interpreter.memory.slice_len(offset, len).to_vec().into()
210 }
211
212 let gas = *interpreter.control.gas();
213 interpreter.control.set_next_action(
214 InterpreterAction::Return {
215 result: InterpreterResult {
216 output,
217 gas,
218 result: instruction_result,
219 },
220 },
221 instruction_result,
222 );
223}
224
225pub fn ret<WIRE: InterpreterTypes, H: Host + ?Sized>(
226 interpreter: &mut Interpreter<WIRE>,
227 _host: &mut H,
228) {
229 return_inner(interpreter, InstructionResult::Return);
230}
231
232pub fn revert<WIRE: InterpreterTypes, H: Host + ?Sized>(
234 interpreter: &mut Interpreter<WIRE>,
235 _host: &mut H,
236) {
237 check!(interpreter, BYZANTIUM);
238 return_inner(interpreter, InstructionResult::Revert);
239}
240
241pub fn stop<WIRE: InterpreterTypes, H: Host + ?Sized>(
243 interpreter: &mut Interpreter<WIRE>,
244 _host: &mut H,
245) {
246 interpreter
247 .control
248 .set_instruction_result(InstructionResult::Stop);
249}
250
251pub fn invalid<WIRE: InterpreterTypes, H: Host + ?Sized>(
253 interpreter: &mut Interpreter<WIRE>,
254 _host: &mut H,
255) {
256 interpreter
257 .control
258 .set_instruction_result(InstructionResult::InvalidFEOpcode);
259}
260
261pub fn unknown<WIRE: InterpreterTypes, H: Host + ?Sized>(
263 interpreter: &mut Interpreter<WIRE>,
264 _host: &mut H,
265) {
266 interpreter
267 .control
268 .set_instruction_result(InstructionResult::OpcodeNotFound);
269}
270
271#[cfg(test)]
272mod test {
273 use super::*;
274 use crate::interpreter::SubRoutineReturnFrame;
275 use crate::{host::DummyHost, instruction_table, interpreter::EthInterpreter};
276 use bytecode::opcode::{CALLF, JUMPF, NOP, RETF, RJUMP, RJUMPI, RJUMPV, STOP};
277 use bytecode::{
278 eof::{CodeInfo, Eof},
279 Bytecode,
280 };
281 use primitives::bytes;
282 use std::sync::Arc;
283
284 #[test]
285 fn rjump() {
286 let bytecode = Bytecode::new_raw(Bytes::from(&[RJUMP, 0x00, 0x02, STOP, STOP]));
287 let mut interpreter = Interpreter::<EthInterpreter>::default().with_bytecode(bytecode);
288
289 interpreter.runtime_flag.is_eof = true;
290 let table = instruction_table();
291 let mut host = DummyHost;
292
293 interpreter.step(&table, &mut host);
294 assert_eq!(interpreter.bytecode.pc(), 5)
295 }
296
297 #[test]
298 fn rjumpi() {
299 let bytecode = Bytecode::new_raw(Bytes::from(&[
300 RJUMPI, 0x00, 0x03, RJUMPI, 0x00, 0x01, STOP, STOP,
301 ]));
302 let mut interpreter = Interpreter::default().with_bytecode(bytecode);
303
304 interpreter.runtime_flag.is_eof = true;
305 let table = instruction_table();
306 let mut host = DummyHost;
307
308 let _ = interpreter.stack.push(U256::from(1));
309 let _ = interpreter.stack.push(U256::from(0));
310
311 interpreter.step(&table, &mut host);
313 assert_eq!(interpreter.bytecode.pc(), 3);
314 interpreter.step(&table, &mut host);
316 assert_eq!(interpreter.bytecode.pc(), 7);
317 }
318
319 #[test]
320 fn rjumpv() {
321 let bytecode = Bytecode::new_raw(Bytes::from(&[
322 RJUMPV,
323 0x01, 0x00, 0x01,
326 0x00, 0x02,
328 NOP,
329 NOP,
330 NOP,
331 RJUMP,
332 0xFF,
333 (-12i8) as u8,
334 STOP,
335 ]));
336 let mut interpreter = Interpreter::default().with_bytecode(bytecode);
337
338 interpreter.runtime_flag.is_eof = true;
339 let table = instruction_table();
340 let mut host = DummyHost;
341
342 let _ = interpreter.stack.push(U256::from(10));
344 interpreter.step(&table, &mut host);
345 assert_eq!(interpreter.bytecode.pc(), 6);
346
347 interpreter.step(&table, &mut host);
349 interpreter.step(&table, &mut host);
350 interpreter.step(&table, &mut host);
351 interpreter.step(&table, &mut host);
352 assert_eq!(interpreter.bytecode.pc(), 0);
353
354 let _ = interpreter.stack.push(U256::from(0));
356 interpreter.step(&table, &mut host);
357 assert_eq!(interpreter.bytecode.pc(), 7);
358
359 interpreter.step(&table, &mut host);
361 interpreter.step(&table, &mut host);
362 interpreter.step(&table, &mut host);
363 assert_eq!(interpreter.bytecode.pc(), 0);
364
365 let _ = interpreter.stack.push(U256::from(1));
367 interpreter.step(&table, &mut host);
368 assert_eq!(interpreter.bytecode.pc(), 8);
369 }
370
371 fn dummy_eof() -> Eof {
372 let bytes = bytes!("ef00010100040200010001ff00000000800000fe");
373 Eof::decode(bytes).unwrap()
374 }
375
376 fn eof_setup(bytes1: Bytes, bytes2: Bytes) -> Interpreter {
377 eof_setup_with_types(bytes1, bytes2, CodeInfo::default())
378 }
379
380 fn eof_setup_with_types(bytes1: Bytes, bytes2: Bytes, types: CodeInfo) -> Interpreter {
382 let mut eof = dummy_eof();
383
384 eof.body.code_section.clear();
385 eof.body.code_info.clear();
386 eof.header.code_sizes.clear();
387
388 eof.header.code_sizes.push(bytes1.len() as u16);
389 eof.body.code_section.push(bytes1.len());
390 eof.body.code_info.push(CodeInfo::new(0, 0, 11));
391
392 eof.header.code_sizes.push(bytes2.len() as u16);
393 eof.body.code_section.push(bytes2.len() + bytes1.len());
394 eof.body.code_info.push(types);
395
396 eof.header.types_size = 2 * 4;
398
399 eof.body.code = Bytes::from([bytes1, bytes2].concat());
400
401 let encoded = eof.encode_slow();
404
405 let bytecode = Bytecode::Eof(Arc::new(Eof::decode(encoded).unwrap()));
406
407 Interpreter::default().with_bytecode(bytecode)
408 }
409
410 #[test]
411 fn callf_retf_stop() {
412 let table = instruction_table();
413 let mut host = DummyHost;
414
415 let bytes1 = Bytes::from([CALLF, 0x00, 0x01, STOP]);
416 let bytes2 = Bytes::from([RETF]);
417 let mut interpreter = eof_setup(bytes1, bytes2.clone());
418 interpreter.runtime_flag.is_eof = true;
419 let base_pc = interpreter.bytecode.pc();
420
421 interpreter.step(&table, &mut host);
423
424 assert_eq!(interpreter.sub_routine.current_code_idx, 1);
425 assert_eq!(
426 interpreter.sub_routine.return_stack[0],
427 SubRoutineReturnFrame::new(0, 3 + base_pc)
428 );
429 assert_eq!(interpreter.bytecode.pc() - base_pc, 4);
431
432 interpreter.step(&table, &mut host);
434
435 assert_eq!(interpreter.sub_routine.current_code_idx, 0);
436 assert_eq!(interpreter.sub_routine.return_stack, Vec::new());
437 assert_eq!(interpreter.bytecode.pc() - base_pc, 3);
439
440 interpreter.step(&table, &mut host);
442 assert_eq!(
443 interpreter.control.instruction_result,
444 InstructionResult::Stop
445 );
446 }
447
448 #[test]
449 fn callf_stop() {
450 let table = instruction_table();
451 let mut host = DummyHost;
452
453 let bytes1 = Bytes::from([CALLF, 0x00, 0x01]);
454 let bytes2 = Bytes::from([STOP]);
455 let mut interpreter = eof_setup(bytes1, bytes2.clone());
456 interpreter.runtime_flag.is_eof = true;
457 let base_pc = interpreter.bytecode.pc();
458
459 interpreter.step(&table, &mut host);
461
462 assert_eq!(interpreter.sub_routine.current_code_idx, 1);
463 assert_eq!(
464 interpreter.sub_routine.return_stack[0],
465 SubRoutineReturnFrame::new(0, 3 + base_pc)
466 );
467 assert_eq!(interpreter.bytecode.pc(), 3 + base_pc);
469
470 interpreter.step(&table, &mut host);
472 assert_eq!(
473 interpreter.control.instruction_result,
474 InstructionResult::Stop
475 );
476 }
477
478 #[test]
479 fn callf_stack_overflow() {
480 let table = instruction_table();
481 let mut host = DummyHost;
482
483 let bytes1 = Bytes::from([CALLF, 0x00, 0x01]);
484 let bytes2 = Bytes::from([STOP]);
485 let mut interpreter =
486 eof_setup_with_types(bytes1, bytes2.clone(), CodeInfo::new(0, 0, 1023));
487 interpreter.runtime_flag.is_eof = true;
488
489 let _ = interpreter.stack.push(U256::from(0));
492 let _ = interpreter.stack.push(U256::from(0));
493
494 interpreter.step(&table, &mut host);
496
497 assert_eq!(
499 interpreter.control.instruction_result,
500 InstructionResult::StackOverflow
501 );
502 }
503
504 #[test]
505 fn jumpf_stop() {
506 let table = instruction_table();
507 let mut host = DummyHost;
508
509 let bytes1 = Bytes::from([JUMPF, 0x00, 0x01]);
510 let bytes2 = Bytes::from([STOP]);
511 let mut interpreter = eof_setup(bytes1, bytes2.clone());
512 interpreter.runtime_flag.is_eof = true;
513 let base_pc = interpreter.bytecode.pc();
514
515 interpreter.step(&table, &mut host);
517
518 assert_eq!(interpreter.sub_routine.current_code_idx, 1);
520 assert!(interpreter.sub_routine.return_stack.is_empty());
521 assert_eq!(interpreter.bytecode.pc(), 3 + base_pc);
523
524 interpreter.step(&table, &mut host);
526 assert_eq!(
527 interpreter.control.instruction_result,
528 InstructionResult::Stop
529 );
530 }
531
532 #[test]
533 fn jumpf_stack_overflow() {
534 let table = instruction_table();
535 let mut host = DummyHost;
536
537 let bytes1 = Bytes::from([JUMPF, 0x00, 0x01, STOP]);
538 let bytes2 = Bytes::from([STOP]);
539 let mut interpreter =
540 eof_setup_with_types(bytes1, bytes2.clone(), CodeInfo::new(0, 0, 1023));
541 interpreter.runtime_flag.is_eof = true;
542
543 let _ = interpreter.stack.push(U256::from(0));
546 let _ = interpreter.stack.push(U256::from(0));
547
548 interpreter.step(&table, &mut host);
550
551 assert_eq!(
553 interpreter.control.instruction_result,
554 InstructionResult::StackOverflow
555 );
556 }
557}