Skip to main content

signet_sim/env/
host.rs

1use crate::{InnerDb, SimDb, TimeLimited};
2use signet_evm::{signet_precompiles, EvmNeedsTx, OrderDetector, SignetLayered};
3use signet_types::constants::SignetSystemConstants;
4use std::{marker::PhantomData, sync::Arc};
5use tokio::time::Instant;
6use trevm::{
7    db::TryCachingDb,
8    helpers::Ctx,
9    inspectors::{Layered, TimeLimit},
10    revm::{
11        context::{BlockEnv, CfgEnv},
12        database::{Cache, CacheDB},
13        inspector::{Inspector, NoOpInspector},
14        DatabaseRef,
15    },
16    Block, Cfg, TrevmBuilder,
17};
18
19/// A host simulation environment.
20#[derive(Debug)]
21pub struct HostEnv<Db, Insp = NoOpInspector> {
22    db: InnerDb<Db>,
23
24    constants: SignetSystemConstants,
25
26    cfg: CfgEnv,
27    block: BlockEnv,
28
29    _pd: PhantomData<fn() -> Insp>,
30}
31
32impl<Db, Insp> Clone for HostEnv<Db, Insp> {
33    fn clone(&self) -> Self {
34        Self {
35            db: self.db.clone(),
36            constants: self.constants.clone(),
37            cfg: self.cfg.clone(),
38            block: self.block.clone(),
39            _pd: PhantomData,
40        }
41    }
42}
43
44impl<Db, Insp> HostEnv<Db, Insp> {
45    /// Create a new host environment.
46    pub fn new<C, B>(db: Db, constants: SignetSystemConstants, cfg_ref: &C, block_ref: &B) -> Self
47    where
48        C: Cfg,
49        B: Block,
50    {
51        let mut cfg = CfgEnv::default();
52        cfg_ref.fill_cfg_env(&mut cfg);
53        let mut block = BlockEnv::default();
54        block_ref.fill_block_env(&mut block);
55
56        Self { db: Arc::new(CacheDB::new(db)), constants, cfg, block, _pd: PhantomData }
57    }
58
59    /// Get a reference to the inner database.
60    pub const fn db(&self) -> &InnerDb<Db> {
61        &self.db
62    }
63
64    /// Get a mutable reference to the inner database.
65    pub const fn db_mut(&mut self) -> &mut InnerDb<Db> {
66        &mut self.db
67    }
68
69    /// Get a reference to the signet system constants.
70    pub const fn constants(&self) -> &SignetSystemConstants {
71        &self.constants
72    }
73
74    /// Get a reference to the [`CfgEnv`].
75    pub const fn cfg(&self) -> &CfgEnv {
76        &self.cfg
77    }
78
79    /// Get a mutable reference to the [`CfgEnv`].
80    pub const fn cfg_mut(&mut self) -> &mut CfgEnv {
81        &mut self.cfg
82    }
83
84    /// Get a reference to the [`BlockEnv`].
85    pub const fn block(&self) -> &BlockEnv {
86        &self.block
87    }
88
89    /// Get a mutable reference to the [`BlockEnv`].
90    pub const fn block_mut(&mut self) -> &mut BlockEnv {
91        &mut self.block
92    }
93}
94
95impl<Db, Insp> HostEnv<Db, Insp>
96where
97    Db: DatabaseRef + Send + Sync,
98    Insp: Inspector<Ctx<SimDb<Db>>> + Default + Sync,
99{
100    /// Connect a fresh database for the simulation.
101    pub fn sim_db(&self) -> crate::SimDb<Db> {
102        crate::SimDb::new(self.db.clone())
103    }
104
105    /// Create a new EVM for the host environment that will finish by the
106    /// given instant.
107    pub fn create_evm(
108        &self,
109        finish_by: Instant,
110    ) -> EvmNeedsTx<crate::SimDb<Db>, TimeLimited<Insp>> {
111        let db = self.sim_db();
112        let inspector = Layered::new(TimeLimit::new(finish_by - Instant::now()), Insp::default());
113
114        // We layer on a order detector specific to the host environment.
115        let inspector =
116            SignetLayered::new(inspector, OrderDetector::for_host(self.constants.clone()));
117
118        // This is the same code as `signet_evm::signet_evm_with_inspector`, but
119        // we need to build the EVM manually to insert our layered inspector,
120        // as the shortcut will insert a rollup order detector.
121        TrevmBuilder::new()
122            .with_db(db)
123            .with_insp(inspector)
124            .with_precompiles(signet_precompiles())
125            .build_trevm()
126            .fill_cfg(&self.cfg)
127            .fill_block(&self.block)
128    }
129}
130
131impl<Db, Insp> HostEnv<Db, Insp>
132where
133    Db: DatabaseRef,
134    Insp: Inspector<Ctx<SimDb<Db>>> + Default + Sync,
135{
136    /// Accepts a cache from the simulation and extends the database with it.
137    pub fn accept_cache(
138        &mut self,
139        cache: Cache,
140    ) -> Result<(), <InnerDb<Db> as TryCachingDb>::Error> {
141        self.db_mut().try_extend(cache)
142    }
143
144    /// Accepts a cache from the simulation and extends the database with it.
145    pub fn accept_cache_ref(
146        &mut self,
147        cache: &Cache,
148    ) -> Result<(), <InnerDb<Db> as TryCachingDb>::Error> {
149        self.db_mut().try_extend_ref(cache)
150    }
151}