1+ use alloc:: format;
12use core:: convert:: Infallible ;
2- use revm:: { Database , DatabaseCommit } ;
3+ use revm:: {
4+ primitives:: { EVMError , ResultAndState } ,
5+ Database , DatabaseCommit ,
6+ } ;
37
4- /// Trait for types that can be used to connect to a database. Connectors
5- /// should contain configuration information like filesystem paths. They are
6- /// intended to enable parallel instantiation of multiple EVMs in multiple
7- /// threads sharing some database configuration
8- pub trait DbConnect : Sync {
8+ use crate :: {
9+ Block , Cfg , EvmErrored , EvmNeedsBlock , EvmNeedsCfg , EvmNeedsTx , EvmReady , EvmTransacted , Tx ,
10+ } ;
11+
12+ /// Trait for types that can be used to connect to a database.
13+ ///
14+ /// Connectors should contain configuration information like filesystem paths.
15+ /// They are intended to enable parallel instantiation of multiple EVMs in
16+ /// multiple threads sharing some database configuration
17+ ///
18+ /// The lifetime on this trait allows the resulting DB to borrow from the
19+ /// connector. E.g. the connector may contain some `Db` and the resulting Db may
20+ /// contain `&Db`. This allows for (e.g.) shared caches between multiple DB
21+ /// threads.
22+ pub trait DbConnect < ' a > : Sync {
923 /// The database type returned when connecting.
1024 type Database : Database + DatabaseCommit ;
1125
1226 /// The error type returned when connecting to the database.
1327 type Error : core:: error:: Error ;
1428
1529 /// Connect to the database.
16- fn connect ( & self ) -> Result < Self :: Database , Self :: Error > ;
30+ fn connect ( & ' a self ) -> Result < Self :: Database , Self :: Error > ;
1731}
1832
19- impl < Db > DbConnect for Db
33+ impl < Db > DbConnect < ' _ > for Db
2034where
2135 Db : Database + DatabaseCommit + Clone + Sync ,
2236{
@@ -28,3 +42,100 @@ where
2842 Ok ( self . clone ( ) )
2943 }
3044}
45+
46+ /// Trait for types that can create EVM instances.
47+ pub trait EvmFactory < ' a > : DbConnect < ' a > {
48+ /// The `Ext` type used in the resulting EVM.
49+ type Ext : Sync ;
50+
51+ /// Create a new EVM instance with the given database connection and
52+ /// extension.
53+ fn create ( & ' a self ) -> Result < EvmNeedsCfg < ' a , Self :: Ext , Self :: Database > , Self :: Error > ;
54+
55+ /// Create a new EVM instance and parameterize it with a [`Cfg`].
56+ fn create_with_cfg < C > (
57+ & ' a self ,
58+ cfg : & C ,
59+ ) -> Result < EvmNeedsBlock < ' a , Self :: Ext , Self :: Database > , Self :: Error >
60+ where
61+ C : Cfg ,
62+ {
63+ self . create ( ) . map ( |evm| evm. fill_cfg ( cfg) )
64+ }
65+
66+ /// Create a new EVM instance and parameterize it with a [`Cfg`] and a
67+ /// [`Block`].
68+ fn create_with_block < C , B > (
69+ & ' a self ,
70+ cfg : & C ,
71+ block : & B ,
72+ ) -> Result < EvmNeedsTx < ' a , Self :: Ext , Self :: Database > , Self :: Error >
73+ where
74+ C : Cfg ,
75+ B : Block ,
76+ {
77+ self . create_with_cfg ( cfg) . map ( |evm| evm. fill_block ( block) )
78+ }
79+
80+ /// Create a new EVM instance, and parameterize it with a [`Cfg`], a
81+ /// [`Block`], and a [`Tx`], yielding an [`EvmReady`].
82+ fn create_with_tx < C , B , T > (
83+ & ' a self ,
84+ cfg : & C ,
85+ block : & B ,
86+ tx : & T ,
87+ ) -> Result < EvmReady < ' a , Self :: Ext , Self :: Database > , Self :: Error >
88+ where
89+ C : Cfg ,
90+ B : Block ,
91+ T : Tx ,
92+ {
93+ self . create_with_block ( cfg, block) . map ( |evm| evm. fill_tx ( tx) )
94+ }
95+
96+ /// Create a new EVM instance, parameterize it with a [`Cfg`], a
97+ /// [`Block`], and a [`Tx`], and run the transaction, yielding either
98+ /// [`EvmTransacted`] or [`EvmErrored`].
99+ #[ allow( clippy:: type_complexity) ]
100+ fn transact < C , B , T > (
101+ & ' a self ,
102+ cfg : & C ,
103+ block : & B ,
104+ tx : & T ,
105+ ) -> Result <
106+ Result <
107+ EvmTransacted < ' a , Self :: Ext , Self :: Database > ,
108+ EvmErrored < ' a , Self :: Ext , Self :: Database > ,
109+ > ,
110+ Self :: Error ,
111+ >
112+ where
113+ C : Cfg ,
114+ B : Block ,
115+ T : Tx ,
116+ {
117+ let evm = self . create_with_tx ( cfg, block, tx) ?;
118+ Ok ( evm. run ( ) )
119+ }
120+
121+ /// Run a transaction, take the [`ResultAndState`], and discard the Evm.
122+ /// This is a high-level shortcut function.
123+ fn run < C , B , T > (
124+ & ' a self ,
125+ cfg : & C ,
126+ block : & B ,
127+ tx : & T ,
128+ ) -> Result < ResultAndState , EVMError < <Self :: Database as Database >:: Error > >
129+ where
130+ C : Cfg ,
131+ B : Block ,
132+ T : Tx ,
133+ {
134+ let trevm = self . transact ( cfg, block, tx) . map_err ( |e| EVMError :: Custom ( format ! ( "{e}" ) ) ) ?;
135+
136+ match trevm {
137+ Ok ( t) => Ok ( t. into_result_and_state ( ) ) ,
138+ Err ( t) => Err ( t. into_error ( ) ) ,
139+ }
140+ }
141+ }
0 commit comments