Skip to main content

revm_handler/
instructions.rs

1use auto_impl::auto_impl;
2use interpreter::{
3    instructions::{gas_table_spec, GasTable, InstructionTable},
4    Host, Instruction, InterpreterTypes,
5};
6use primitives::hardfork::SpecId;
7use std::boxed::Box;
8
9/// Stores instructions for EVM.
10#[auto_impl(&mut, Box)]
11pub trait InstructionProvider {
12    /// Context type.
13    type Context;
14    /// Interpreter types.
15    type InterpreterTypes: InterpreterTypes;
16
17    /// Returns the instruction table that is used by EvmTr to execute instructions.
18    fn instruction_table(&self) -> &InstructionTable<Self::InterpreterTypes, Self::Context>;
19
20    /// Returns the gas table for static gas costs.
21    fn gas_table(&self) -> &GasTable;
22}
23
24/// Ethereum instruction contains list of mainnet instructions that is used for Interpreter execution.
25#[derive(Debug)]
26pub struct EthInstructions<WIRE: InterpreterTypes, HOST: ?Sized> {
27    /// Spec that is used to set gas costs for instructions.
28    pub spec: SpecId,
29    inner: Box<EthInstructionsInner<WIRE, HOST>>,
30}
31
32#[derive(Debug)]
33struct EthInstructionsInner<WIRE: InterpreterTypes, HOST: ?Sized> {
34    /// Table containing instruction implementations indexed by opcode.
35    instruction_table: InstructionTable<WIRE, HOST>,
36    /// Static gas cost table indexed by opcode.
37    gas_table: GasTable,
38}
39
40impl<WIRE, HOST: Host + ?Sized> Clone for EthInstructions<WIRE, HOST>
41where
42    WIRE: InterpreterTypes,
43{
44    fn clone(&self) -> Self {
45        Self {
46            spec: self.spec,
47            inner: self.inner.clone(),
48        }
49    }
50}
51
52impl<WIRE, HOST: Host + ?Sized> Clone for EthInstructionsInner<WIRE, HOST>
53where
54    WIRE: InterpreterTypes,
55{
56    fn clone(&self) -> Self {
57        *self
58    }
59}
60impl<WIRE, HOST: Host + ?Sized> Copy for EthInstructionsInner<WIRE, HOST> where
61    WIRE: InterpreterTypes
62{
63}
64
65impl<WIRE, HOST> EthInstructions<WIRE, HOST>
66where
67    WIRE: InterpreterTypes,
68    HOST: Host,
69{
70    /// Returns `EthInstructions` with mainnet spec.
71    #[deprecated(since = "0.2.0", note = "use new_mainnet_with_spec instead")]
72    pub fn new_mainnet() -> Self {
73        let spec = SpecId::default();
74        Self::new_mainnet_with_spec(spec)
75    }
76
77    /// Returns `EthInstructions` with mainnet spec.
78    pub fn new_mainnet_with_spec(spec: SpecId) -> Self {
79        Self::new(interpreter::instruction_table(), gas_table_spec(spec), spec)
80    }
81
82    /// Returns a new instance of `EthInstructions` with custom instruction and gas tables.
83    pub fn new(
84        instruction_table: InstructionTable<WIRE, HOST>,
85        gas_table: GasTable,
86        spec: SpecId,
87    ) -> Self {
88        Self {
89            spec,
90            inner: Box::new(EthInstructionsInner {
91                instruction_table,
92                gas_table,
93            }),
94        }
95    }
96
97    /// Inserts a new instruction into the instruction table.
98    #[inline]
99    pub fn insert_instruction(
100        &mut self,
101        opcode: u8,
102        instruction: Instruction<WIRE, HOST>,
103        gas: u16,
104    ) {
105        self.inner.instruction_table[opcode as usize] = instruction;
106        self.inner.gas_table[opcode as usize] = gas;
107    }
108
109    /// Inserts a new gas cost into the gas table.
110    #[inline]
111    pub fn insert_gas(&mut self, opcode: u8, gas: u16) {
112        self.inner.gas_table[opcode as usize] = gas;
113    }
114
115    /// Returns a reference to the instruction table.
116    #[inline]
117    pub fn instruction_table(&self) -> &InstructionTable<WIRE, HOST> {
118        &self.inner.instruction_table
119    }
120
121    /// Returns a mutable reference to the instruction table.
122    #[inline]
123    pub fn instruction_table_mut(&mut self) -> &mut InstructionTable<WIRE, HOST> {
124        &mut self.inner.instruction_table
125    }
126
127    /// Returns a reference to the gas table.
128    #[inline]
129    pub fn gas_table(&self) -> &GasTable {
130        &self.inner.gas_table
131    }
132
133    /// Returns a mutable reference to the gas table.
134    #[inline]
135    pub fn gas_table_mut(&mut self) -> &mut GasTable {
136        &mut self.inner.gas_table
137    }
138}
139
140impl<IT, CTX> InstructionProvider for EthInstructions<IT, CTX>
141where
142    IT: InterpreterTypes,
143    CTX: Host,
144{
145    type InterpreterTypes = IT;
146    type Context = CTX;
147
148    #[inline]
149    fn instruction_table(&self) -> &InstructionTable<Self::InterpreterTypes, Self::Context> {
150        self.instruction_table()
151    }
152
153    #[inline]
154    fn gas_table(&self) -> &GasTable {
155        self.gas_table()
156    }
157}