Skip to main content

revm_handler/
instructions.rs

1use auto_impl::auto_impl;
2use interpreter::{
3    instructions::{instruction_table_gas_changes_spec, 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
21/// Ethereum instruction contains list of mainnet instructions that is used for Interpreter execution.
22#[derive(Debug)]
23pub struct EthInstructions<WIRE: InterpreterTypes, HOST: ?Sized> {
24    /// Table containing instruction implementations indexed by opcode.
25    pub instruction_table: Box<InstructionTable<WIRE, HOST>>,
26    /// Spec that is used to set gas costs for instructions.
27    pub spec: SpecId,
28}
29
30impl<WIRE, HOST: Host + ?Sized> Clone for EthInstructions<WIRE, HOST>
31where
32    WIRE: InterpreterTypes,
33{
34    fn clone(&self) -> Self {
35        Self {
36            instruction_table: self.instruction_table.clone(),
37            spec: self.spec,
38        }
39    }
40}
41
42impl<WIRE, HOST> EthInstructions<WIRE, HOST>
43where
44    WIRE: InterpreterTypes,
45    HOST: Host,
46{
47    /// Returns `EthInstructions` with mainnet spec.
48    #[deprecated(since = "0.2.0", note = "use new_mainnet_with_spec instead")]
49    pub fn new_mainnet() -> Self {
50        let spec = SpecId::default();
51        Self::new(instruction_table_gas_changes_spec(spec), spec)
52    }
53
54    /// Returns `EthInstructions` with mainnet spec.
55    pub fn new_mainnet_with_spec(spec: SpecId) -> Self {
56        Self::new(instruction_table_gas_changes_spec(spec), spec)
57    }
58
59    /// Returns a new instance of `EthInstructions` with custom instruction table.
60    #[inline]
61    pub fn new(base_table: InstructionTable<WIRE, HOST>, spec: SpecId) -> Self {
62        Self {
63            instruction_table: Box::new(base_table),
64            spec,
65        }
66    }
67
68    /// Inserts a new instruction into the instruction table.
69    #[inline]
70    pub fn insert_instruction(&mut self, opcode: u8, instruction: Instruction<WIRE, HOST>) {
71        self.instruction_table[opcode as usize] = instruction;
72    }
73}
74
75impl<IT, CTX> InstructionProvider for EthInstructions<IT, CTX>
76where
77    IT: InterpreterTypes,
78    CTX: Host,
79{
80    type InterpreterTypes = IT;
81    type Context = CTX;
82
83    fn instruction_table(&self) -> &InstructionTable<Self::InterpreterTypes, Self::Context> {
84        &self.instruction_table
85    }
86}