revm_optimism/handler/
precompiles.rs1use crate::OpSpecId;
2use once_cell::race::OnceBox;
3use precompile::{secp256r1, PrecompileError, Precompiles};
4use revm::{
5 context::Cfg,
6 context_interface::ContextTr,
7 handler::{EthPrecompiles, PrecompileProvider},
8 interpreter::InterpreterResult,
9};
10use std::boxed::Box;
11
12pub struct OpPrecompileProvider<CTX> {
13 precompile_provider: EthPrecompiles<CTX>,
14}
15
16impl<CTX> Clone for OpPrecompileProvider<CTX> {
17 fn clone(&self) -> Self {
18 Self {
19 precompile_provider: self.precompile_provider.clone(),
20 }
21 }
22}
23
24impl<CTX> OpPrecompileProvider<CTX> {
25 pub fn new(precompiles: &'static Precompiles) -> Self {
26 Self {
27 precompile_provider: EthPrecompiles {
28 precompiles,
29 _phantom: core::marker::PhantomData,
30 },
31 }
32 }
33
34 #[inline]
35 pub fn new_with_spec(spec: OpSpecId) -> Self {
36 match spec {
37 spec @ (OpSpecId::BEDROCK
38 | OpSpecId::REGOLITH
39 | OpSpecId::CANYON
40 | OpSpecId::ECOTONE) => Self::new(Precompiles::new(spec.into_eth_spec().into())),
41 OpSpecId::FJORD => Self::new(fjord()),
42 OpSpecId::GRANITE | OpSpecId::HOLOCENE => Self::new(granite()),
43 OpSpecId::ISTHMUS | OpSpecId::INTEROP => Self::new(isthumus()),
44 }
45 }
46}
47
48pub fn fjord() -> &'static Precompiles {
50 static INSTANCE: OnceBox<Precompiles> = OnceBox::new();
51 INSTANCE.get_or_init(|| {
52 let mut precompiles = Precompiles::cancun().clone();
53 precompiles.extend([crate::bn128::pair::GRANITE]);
55 Box::new(precompiles)
56 })
57}
58
59pub fn granite() -> &'static Precompiles {
61 static INSTANCE: OnceBox<Precompiles> = OnceBox::new();
62 INSTANCE.get_or_init(|| {
63 let mut precompiles = Precompiles::cancun().clone();
64 precompiles.extend([secp256r1::P256VERIFY]);
66 Box::new(precompiles)
67 })
68}
69
70pub fn isthumus() -> &'static Precompiles {
72 static INSTANCE: OnceBox<Precompiles> = OnceBox::new();
73 INSTANCE.get_or_init(|| {
74 let precompiles = granite().clone();
75 #[cfg(feature = "blst")]
78 let precompiles = {
79 let mut precompiles = precompiles;
80 precompiles.extend(precompile::bls12_381::precompiles());
81 precompiles
82 };
83 Box::new(precompiles)
84 })
85}
86
87impl<CTX> PrecompileProvider for OpPrecompileProvider<CTX>
88where
89 CTX: ContextTr<Cfg: Cfg<Spec = OpSpecId>>,
90{
91 type Context = CTX;
92 type Output = InterpreterResult;
93
94 #[inline]
95 fn set_spec(&mut self, spec: <<Self::Context as ContextTr>::Cfg as Cfg>::Spec) {
96 *self = Self::new_with_spec(spec);
97 }
98
99 #[inline]
100 fn run(
101 &mut self,
102 context: &mut Self::Context,
103 address: &precompile::Address,
104 bytes: &precompile::Bytes,
105 gas_limit: u64,
106 ) -> Result<Option<Self::Output>, PrecompileError> {
107 self.precompile_provider
108 .run(context, address, bytes, gas_limit)
109 }
110
111 #[inline]
112 fn warm_addresses(&self) -> Box<impl Iterator<Item = precompile::Address> + '_> {
113 self.precompile_provider.warm_addresses()
114 }
115
116 #[inline]
117 fn contains(&self, address: &precompile::Address) -> bool {
118 self.precompile_provider.contains(address)
119 }
120}
121
122impl<CTX> Default for OpPrecompileProvider<CTX> {
123 fn default() -> Self {
124 Self::new_with_spec(OpSpecId::ISTHMUS)
125 }
126}