evm_interpreter/interpreter/
valids.rs

1use alloc::vec::Vec;
2
3use crate::opcode::Opcode;
4
5/// Mapping of valid jump destination from code.
6#[derive(Clone, Debug, Eq, PartialEq)]
7pub struct Valids(Vec<bool>);
8
9impl Valids {
10	/// Create a new valid mapping from given code bytes.
11	#[must_use]
12	pub fn new(code: &[u8]) -> Self {
13		let mut valids: Vec<bool> = Vec::with_capacity(code.len());
14		valids.resize(code.len(), false);
15
16		let mut i = 0;
17		while i < code.len() {
18			let opcode = Opcode(code[i]);
19			if opcode == Opcode::JUMPDEST {
20				valids[i] = true;
21				i += 1;
22			} else if let Some(v) = opcode.is_push() {
23				i += v as usize + 1;
24			} else {
25				i += 1;
26			}
27		}
28
29		Self(valids)
30	}
31
32	/// Returns `true` if the position is a valid jump destination.
33	/// If not, returns `false`.
34	#[must_use]
35	pub fn is_valid(&self, position: usize) -> bool {
36		if position >= self.0.len() {
37			return false;
38		}
39
40		self.0[position]
41	}
42}