revm_handler/
instructions.rs1use auto_impl::auto_impl;
2use interpreter::{
3 gas::params::GasParams,
4 instructions::{instruction_table_gas_changes_spec, InstructionTable},
5 Host, Instruction, InterpreterTypes,
6};
7use primitives::hardfork::SpecId;
8use std::boxed::Box;
9
10#[auto_impl(&mut, Box)]
12pub trait InstructionProvider {
13 type Context;
15 type InterpreterTypes: InterpreterTypes;
17
18 fn instruction_table(&self) -> &InstructionTable<Self::InterpreterTypes, Self::Context>;
20
21 fn gas_params(&self) -> GasParams;
23
24 fn set_spec(&mut self, spec: SpecId) -> bool;
26}
27
28#[derive(Debug)]
30pub struct EthInstructions<WIRE: InterpreterTypes, HOST: ?Sized> {
31 pub instruction_table: Box<InstructionTable<WIRE, HOST>>,
33 pub gas_params: GasParams,
35 pub spec: SpecId,
37}
38
39impl<WIRE, HOST: Host + ?Sized> Clone for EthInstructions<WIRE, HOST>
40where
41 WIRE: InterpreterTypes,
42{
43 fn clone(&self) -> Self {
44 Self {
45 instruction_table: self.instruction_table.clone(),
46 gas_params: self.gas_params.clone(),
47 spec: self.spec,
48 }
49 }
50}
51
52impl<WIRE, HOST> EthInstructions<WIRE, HOST>
53where
54 WIRE: InterpreterTypes,
55 HOST: Host,
56{
57 pub fn new_mainnet() -> Self {
59 let spec = SpecId::default();
60 Self::new(
61 instruction_table_gas_changes_spec(spec),
62 GasParams::new_spec(spec),
63 spec,
64 )
65 }
66
67 #[inline]
69 pub fn new(
70 base_table: InstructionTable<WIRE, HOST>,
71 gas_params: GasParams,
72 spec: SpecId,
73 ) -> Self {
74 Self {
75 instruction_table: Box::new(base_table),
76 gas_params,
77 spec,
78 }
79 }
80
81 #[inline]
83 pub fn insert_instruction(&mut self, opcode: u8, instruction: Instruction<WIRE, HOST>) {
84 self.instruction_table[opcode as usize] = instruction;
85 }
86}
87
88impl<IT, CTX> InstructionProvider for EthInstructions<IT, CTX>
89where
90 IT: InterpreterTypes,
91 CTX: Host,
92{
93 type InterpreterTypes = IT;
94 type Context = CTX;
95
96 fn instruction_table(&self) -> &InstructionTable<Self::InterpreterTypes, Self::Context> {
97 &self.instruction_table
98 }
99
100 fn gas_params(&self) -> GasParams {
101 self.gas_params.clone()
102 }
103
104 fn set_spec(&mut self, spec: SpecId) -> bool {
105 if spec == self.spec {
106 return false;
107 }
108 *self.instruction_table = instruction_table_gas_changes_spec(spec);
109 self.gas_params = GasParams::new_spec(spec);
110
111 true
112 }
113}
114
115impl<WIRE, HOST> Default for EthInstructions<WIRE, HOST>
116where
117 WIRE: InterpreterTypes,
118 HOST: Host,
119{
120 fn default() -> Self {
121 Self::new_mainnet()
122 }
123}