1
+ use alloc:: format;
1
2
use core:: convert:: Infallible ;
2
- use revm:: { Database , DatabaseCommit } ;
3
+ use revm:: {
4
+ primitives:: { EVMError , ResultAndState } ,
5
+ Database , DatabaseCommit ,
6
+ } ;
3
7
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 {
9
23
/// The database type returned when connecting.
10
24
type Database : Database + DatabaseCommit ;
11
25
12
26
/// The error type returned when connecting to the database.
13
27
type Error : core:: error:: Error ;
14
28
15
29
/// Connect to the database.
16
- fn connect ( & self ) -> Result < Self :: Database , Self :: Error > ;
30
+ fn connect ( & ' a self ) -> Result < Self :: Database , Self :: Error > ;
17
31
}
18
32
19
- impl < Db > DbConnect for Db
33
+ impl < Db > DbConnect < ' _ > for Db
20
34
where
21
35
Db : Database + DatabaseCommit + Clone + Sync ,
22
36
{
@@ -28,3 +42,100 @@ where
28
42
Ok ( self . clone ( ) )
29
43
}
30
44
}
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