evm_core/
valids.rs

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