use crate::{evm::Trevm, helpers::Ctx, EvmNeedsCfg};
use revm::{
handler::EthPrecompiles, inspector::NoOpInspector, precompile::Precompiles,
primitives::hardfork::SpecId, Database, Inspector, MainBuilder,
};
#[derive(Debug, Clone, thiserror::Error)]
#[non_exhaustive]
pub enum TrevmBuilderError {
#[error("Database not set")]
DatabaseNotSet,
}
#[allow(unnameable_types)]
#[derive(Debug, Copy, Clone)]
pub struct BuilderNeedsDb {
_private: (),
}
#[allow(unnameable_types)]
#[derive(Debug, Copy, Clone)]
pub struct BuilderReady<Db> {
db: Db,
}
#[derive(Debug, Clone)]
pub struct TrevmBuilder<Insp, State = BuilderNeedsDb> {
pub(crate) insp: Insp,
pub(crate) spec: SpecId,
pub(crate) precompiles: Option<&'static Precompiles>,
pub(crate) state: State,
}
impl TrevmBuilder<NoOpInspector> {
#[allow(clippy::new_without_default)] pub const fn new() -> Self {
Self {
insp: NoOpInspector,
spec: SpecId::PRAGUE,
precompiles: None,
state: BuilderNeedsDb { _private: () },
}
}
}
impl<Insp, State> TrevmBuilder<Insp, State> {
pub fn with_db<Odb>(self, db: Odb) -> TrevmBuilder<Insp, BuilderReady<Odb>>
where
Odb: Database,
{
TrevmBuilder {
insp: self.insp,
spec: self.spec,
precompiles: self.precompiles,
state: BuilderReady { db },
}
}
pub fn with_insp<OInsp>(self, insp: OInsp) -> TrevmBuilder<OInsp, State> {
TrevmBuilder { insp, spec: self.spec, precompiles: self.precompiles, state: self.state }
}
pub fn with_inspector<OInsp>(self, insp: OInsp) -> TrevmBuilder<OInsp, State> {
self.with_insp(insp)
}
pub const fn with_spec_id(mut self, spec: SpecId) -> Self {
self.spec = spec;
self
}
pub const fn with_precompiles(mut self, precompiles: &'static Precompiles) -> Self {
self.precompiles = Some(precompiles);
self
}
pub fn with_precompiles_from_spec(mut self) -> Self {
self.precompiles = Some(Precompiles::new(self.spec.into()));
self
}
}
impl<Insp, Db> TrevmBuilder<Insp, BuilderReady<Db>> {
pub fn build_trevm(self) -> EvmNeedsCfg<Db, Insp>
where
Db: Database,
Insp: Inspector<Ctx<Db>>,
{
let db = self.state.db;
let ctx = Ctx::new(db, self.spec);
let mut evm = ctx.build_mainnet_with_inspector(self.insp);
if let Some(precompiles) = self.precompiles {
evm.precompiles = EthPrecompiles { precompiles, spec: self.spec };
}
Trevm::from(evm)
}
}