Skip to main content

evm/standard/
mod.rs

1//! # Standard machines and gasometers
2//!
3//! This module implements the standard configurations of the interpreter, like how it works on
4//! Ethereum mainnet. Most of them can still be customized to add additional functionality, by
5//! wrapping them or replacing the generic parameters.
6
7mod config;
8mod gasometer;
9mod invoker;
10
11use alloc::vec::Vec;
12use core::marker::PhantomData;
13
14use evm_interpreter::uint::{H160, H256, U256};
15use evm_interpreter::{
16	Control, ExitError, etable, eval,
17	runtime::{GasState, RuntimeBackend, RuntimeConfig, RuntimeEnvironment, RuntimeState},
18	trap::CallCreateTrap,
19};
20
21pub use self::{
22	config::Config,
23	gasometer::{GasometerState, eval as eval_gasometer},
24	invoker::{
25		EtableResolver, Invoker, InvokerState, PrecompileSet, Resolver, ResolverOrigin,
26		SubstackInvoke, TransactArgs, TransactArgsCallCreate, TransactGasPrice, TransactInvoke,
27		TransactValue, TransactValueCallCreate, routines,
28	},
29};
30use crate::{MergeStrategy, gasometer::GasMutState};
31
32/// Standard machine.
33pub type Machine<'config> = evm_interpreter::Machine<State<'config>>;
34
35/// Standard Etable opcode handle function.
36pub type Efn<'config, H> = etable::Efn<State<'config>, H, CallCreateTrap>;
37
38/// Standard Etable.
39pub type DispatchEtable<'config, H, F = Efn<'config, H>> =
40	etable::DispatchEtable<State<'config>, H, CallCreateTrap, F>;
41
42/// Gasometer Etable.
43pub struct GasometerEtable<'config>(PhantomData<&'config ()>);
44
45impl<'config> GasometerEtable<'config> {
46	/// Create a new gasometer etable.
47	pub const fn new() -> Self {
48		Self(PhantomData)
49	}
50}
51
52impl<'config> Default for GasometerEtable<'config> {
53	fn default() -> Self {
54		Self::new()
55	}
56}
57
58impl<'config, H> etable::Etable<H> for GasometerEtable<'config>
59where
60	H: RuntimeBackend,
61{
62	type State = State<'config>;
63	type Trap = CallCreateTrap;
64
65	fn eval(
66		&self,
67		machine: &mut Machine<'config>,
68		handle: &mut H,
69		position: usize,
70	) -> Control<Self::Trap> {
71		eval_gasometer(machine, handle, position)
72	}
73}
74
75/// Execution etable.
76pub struct ExecutionEtable<'config>(PhantomData<&'config ()>);
77
78impl<'config> ExecutionEtable<'config> {
79	/// Create a new execution etable.
80	pub const fn new() -> Self {
81		Self(PhantomData)
82	}
83}
84
85impl<'config> Default for ExecutionEtable<'config> {
86	fn default() -> Self {
87		Self::new()
88	}
89}
90
91impl<'config, H> etable::Etable<H> for ExecutionEtable<'config>
92where
93	H: RuntimeBackend + RuntimeEnvironment,
94{
95	type State = State<'config>;
96	type Trap = CallCreateTrap;
97
98	fn eval(
99		&self,
100		machine: &mut Machine<'config>,
101		handle: &mut H,
102		position: usize,
103	) -> Control<Self::Trap> {
104		eval::eval_any(machine, handle, position)
105	}
106}
107
108/// Standard state.
109pub struct State<'config> {
110	/// Runtime state.
111	pub runtime: RuntimeState,
112	/// Gasometer state.
113	pub gasometer: GasometerState,
114	/// Current config.
115	pub config: &'config Config,
116}
117
118impl<'config> AsRef<RuntimeState> for State<'config> {
119	fn as_ref(&self) -> &RuntimeState {
120		&self.runtime
121	}
122}
123
124impl<'config> AsMut<RuntimeState> for State<'config> {
125	fn as_mut(&mut self) -> &mut RuntimeState {
126		&mut self.runtime
127	}
128}
129
130impl<'config> AsRef<GasometerState> for State<'config> {
131	fn as_ref(&self) -> &GasometerState {
132		&self.gasometer
133	}
134}
135
136impl<'config> AsMut<GasometerState> for State<'config> {
137	fn as_mut(&mut self) -> &mut GasometerState {
138		&mut self.gasometer
139	}
140}
141
142impl<'config> AsRef<Config> for State<'config> {
143	fn as_ref(&self) -> &Config {
144		self.config
145	}
146}
147
148impl<'config> AsRef<RuntimeConfig> for State<'config> {
149	fn as_ref(&self) -> &RuntimeConfig {
150		&self.config.runtime
151	}
152}
153
154impl<'config> GasState for State<'config> {
155	fn gas(&self) -> U256 {
156		self.gasometer.gas()
157	}
158}
159
160impl<'config> GasMutState for State<'config> {
161	fn record_gas(&mut self, gas: U256) -> Result<(), ExitError> {
162		self.gasometer.record_gas(gas)
163	}
164}
165
166impl<'config> InvokerState for State<'config> {
167	type TransactArgs = TransactArgs<'config>;
168
169	fn new_transact_call(
170		runtime: RuntimeState,
171		gas_limit: U256,
172		data: &[u8],
173		access_list: &[(H160, Vec<H256>)],
174		args: &TransactArgs<'config>,
175	) -> Result<Self, ExitError> {
176		let config = args.config;
177		Ok(Self {
178			runtime,
179			gasometer: GasometerState::new_transact_call(gas_limit, data, access_list, config)?,
180			config,
181		})
182	}
183
184	fn new_transact_create(
185		runtime: RuntimeState,
186		gas_limit: U256,
187		code: &[u8],
188		access_list: &[(H160, Vec<H256>)],
189		args: &TransactArgs<'config>,
190	) -> Result<Self, ExitError> {
191		let config = args.config;
192		Ok(Self {
193			runtime,
194			gasometer: GasometerState::new_transact_create(gas_limit, code, access_list, config)?,
195			config,
196		})
197	}
198
199	fn substate(
200		&mut self,
201		runtime: RuntimeState,
202		gas_limit: U256,
203		is_static: bool,
204		call_has_value: bool,
205	) -> Result<Self, ExitError> {
206		Ok(Self {
207			runtime,
208			gasometer: self.gasometer.submeter(
209				gas_limit,
210				is_static,
211				call_has_value,
212				self.config,
213			)?,
214			config: self.config,
215		})
216	}
217
218	fn merge(&mut self, substate: Self, strategy: MergeStrategy) {
219		self.gasometer.merge(substate.gasometer, strategy)
220	}
221
222	fn record_codedeposit(&mut self, len: usize) -> Result<(), ExitError> {
223		self.gasometer.record_codedeposit(len)
224	}
225
226	fn is_static(&self) -> bool {
227		self.gasometer.is_static
228	}
229
230	fn effective_gas(&self, with_refund: bool) -> U256 {
231		self.gasometer.effective_gas(with_refund, self.config)
232	}
233}