@@ -23,9 +23,11 @@ pub enum Chain {
23
23
Holesky ,
24
24
Sepolia ,
25
25
Helder ,
26
- Custom { genesis_time_secs : u64 , slot_time_secs : u64 , genesis_fork_version : [ u8 ; 4 ] } ,
26
+ Custom { genesis_time_secs : u64 , slot_time_secs : u64 , genesis_fork_version : ForkVersion } ,
27
27
}
28
28
29
+ pub type ForkVersion = [ u8 ; 4 ] ;
30
+
29
31
impl std:: fmt:: Debug for Chain {
30
32
fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
31
33
match self {
@@ -54,7 +56,7 @@ impl Chain {
54
56
}
55
57
}
56
58
57
- pub fn genesis_fork_version ( & self ) -> [ u8 ; 4 ] {
59
+ pub fn genesis_fork_version ( & self ) -> ForkVersion {
58
60
match self {
59
61
Chain :: Mainnet => KnownChain :: Mainnet . genesis_fork_version ( ) ,
60
62
Chain :: Holesky => KnownChain :: Holesky . genesis_fork_version ( ) ,
@@ -120,7 +122,7 @@ impl KnownChain {
120
122
}
121
123
}
122
124
123
- pub fn genesis_fork_version ( & self ) -> [ u8 ; 4 ] {
125
+ pub fn genesis_fork_version ( & self ) -> ForkVersion {
124
126
match self {
125
127
KnownChain :: Mainnet => hex ! ( "00000000" ) ,
126
128
KnownChain :: Holesky => hex ! ( "01017000" ) ,
@@ -163,8 +165,19 @@ impl From<KnownChain> for Chain {
163
165
#[ serde( untagged) ]
164
166
pub enum ChainLoader {
165
167
Known ( KnownChain ) ,
166
- Path ( PathBuf ) ,
167
- Custom { genesis_time_secs : u64 , slot_time_secs : u64 , genesis_fork_version : Bytes } ,
168
+ Path {
169
+ /// Genesis time as returned in /eth/v1/beacon/genesis
170
+ genesis_time_secs : u64 ,
171
+ /// Path to the genesis spec, as returned by /eth/v1/config/spec
172
+ /// either in JSON or YAML format
173
+ path : PathBuf ,
174
+ } ,
175
+ Custom {
176
+ /// Genesis time as returned in /eth/v1/beacon/genesis
177
+ genesis_time_secs : u64 ,
178
+ slot_time_secs : u64 ,
179
+ genesis_fork_version : Bytes ,
180
+ } ,
168
181
}
169
182
170
183
impl Serialize for Chain {
@@ -199,48 +212,40 @@ impl<'de> Deserialize<'de> for Chain {
199
212
200
213
match loader {
201
214
ChainLoader :: Known ( known) => Ok ( Chain :: from ( known) ) ,
202
- ChainLoader :: Path ( path) => load_chain_from_file ( path) . map_err ( serde:: de:: Error :: custom) ,
215
+ ChainLoader :: Path { genesis_time_secs, path } => {
216
+ let ( slot_time_secs, genesis_fork_version) =
217
+ load_chain_from_file ( path) . map_err ( serde:: de:: Error :: custom) ?;
218
+ Ok ( Chain :: Custom { genesis_time_secs, slot_time_secs, genesis_fork_version } )
219
+ }
203
220
ChainLoader :: Custom { genesis_time_secs, slot_time_secs, genesis_fork_version } => {
204
- let genesis_fork_version: [ u8 ; 4 ] =
221
+ let genesis_fork_version: ForkVersion =
205
222
genesis_fork_version. as_ref ( ) . try_into ( ) . map_err ( serde:: de:: Error :: custom) ?;
206
223
Ok ( Chain :: Custom { genesis_time_secs, slot_time_secs, genesis_fork_version } )
207
224
}
208
225
}
209
226
}
210
227
}
211
228
212
- /// Load a chain config from a spec file , such as returned by
213
- /// /eth/v1/config/spec ref: https://ethereum.github.io/beacon-APIs/#/Config/getSpec
229
+ /// Returns seconds_per_slot and genesis_fork_version from a spec, such as
230
+ /// returned by /eth/v1/config/spec ref: https://ethereum.github.io/beacon-APIs/#/Config/getSpec
214
231
/// Try to load two formats:
215
232
/// - JSON as return the getSpec endpoint, either with or without the `data`
216
233
/// field
217
234
/// - YAML as used e.g. in Kurtosis/Ethereum Package
218
- pub fn load_chain_from_file ( path : PathBuf ) -> eyre:: Result < Chain > {
235
+ pub fn load_chain_from_file ( path : PathBuf ) -> eyre:: Result < ( u64 , ForkVersion ) > {
219
236
#[ derive( Deserialize ) ]
220
237
#[ serde( rename_all = "UPPERCASE" ) ]
221
238
struct QuotedSpecFile {
222
- #[ serde( with = "serde_utils::quoted_u64" ) ]
223
- min_genesis_time : u64 ,
224
- #[ serde( with = "serde_utils::quoted_u64" ) ]
225
- genesis_delay : u64 ,
226
239
#[ serde( with = "serde_utils::quoted_u64" ) ]
227
240
seconds_per_slot : u64 ,
228
241
genesis_fork_version : Bytes ,
229
242
}
230
243
231
244
impl QuotedSpecFile {
232
- fn to_chain ( & self ) -> eyre:: Result < Chain > {
233
- let genesis_fork_version: [ u8 ; 4 ] = self . genesis_fork_version . as_ref ( ) . try_into ( ) ?;
234
-
235
- Ok ( Chain :: Custom {
236
- // note that this can be wrong, (e.g. it's wrong in mainnet). The correct
237
- // value should come from /eth/v1/beacon/genesis
238
- // more info here: https://kb.beaconcha.in/ethereum-staking/the-genesis-event
239
- // FIXME
240
- genesis_time_secs : self . min_genesis_time + self . genesis_delay ,
241
- slot_time_secs : self . seconds_per_slot ,
242
- genesis_fork_version,
243
- } )
245
+ fn to_chain ( & self ) -> eyre:: Result < ( u64 , ForkVersion ) > {
246
+ let genesis_fork_version: ForkVersion =
247
+ self . genesis_fork_version . as_ref ( ) . try_into ( ) ?;
248
+ Ok ( ( self . seconds_per_slot , genesis_fork_version) )
244
249
}
245
250
}
246
251
@@ -252,21 +257,14 @@ pub fn load_chain_from_file(path: PathBuf) -> eyre::Result<Chain> {
252
257
#[ derive( Deserialize ) ]
253
258
#[ serde( rename_all = "UPPERCASE" ) ]
254
259
struct SpecFile {
255
- min_genesis_time : u64 ,
256
- genesis_delay : u64 ,
257
260
seconds_per_slot : u64 ,
258
261
genesis_fork_version : u32 ,
259
262
}
260
263
261
264
impl SpecFile {
262
- fn to_chain ( & self ) -> Chain {
263
- let genesis_fork_version: [ u8 ; 4 ] = self . genesis_fork_version . to_be_bytes ( ) ;
264
-
265
- Chain :: Custom {
266
- genesis_time_secs : self . min_genesis_time + self . genesis_delay ,
267
- slot_time_secs : self . seconds_per_slot ,
268
- genesis_fork_version,
269
- }
265
+ fn to_chain ( & self ) -> ( u64 , ForkVersion ) {
266
+ let genesis_fork_version: ForkVersion = self . genesis_fork_version . to_be_bytes ( ) ;
267
+ ( self . seconds_per_slot , genesis_fork_version)
270
268
}
271
269
}
272
270
@@ -320,11 +318,11 @@ mod tests {
320
318
path. pop ( ) ;
321
319
path. push ( "tests/data/mainnet_spec_data.json" ) ;
322
320
323
- let s = format ! ( "chain = {path:? }" ) ;
321
+ let s = format ! ( "chain = {{ genesis_time_secs = 1, path = {path:?}} }" ) ;
324
322
325
323
let decoded: MockConfig = toml:: from_str ( & s) . unwrap ( ) ;
326
324
327
- // see fixme in load_chain_from_file
325
+ assert_eq ! ( decoded . chain . genesis_time_sec ( ) , 1 ) ;
328
326
assert_eq ! ( decoded. chain. slot_time_sec( ) , KnownChain :: Mainnet . slot_time_sec( ) ) ;
329
327
assert_eq ! (
330
328
decoded. chain. genesis_fork_version( ) ,
@@ -341,11 +339,11 @@ mod tests {
341
339
path. pop ( ) ;
342
340
path. push ( "tests/data/holesky_spec.json" ) ;
343
341
344
- let s = format ! ( "chain = {path:? }" ) ;
342
+ let s = format ! ( "chain = {{ genesis_time_secs = 1, path = {path:?}} }" ) ;
345
343
346
344
let decoded: MockConfig = toml:: from_str ( & s) . unwrap ( ) ;
347
345
assert_eq ! ( decoded. chain, Chain :: Custom {
348
- genesis_time_secs: KnownChain :: Holesky . genesis_time_sec ( ) ,
346
+ genesis_time_secs: 1 ,
349
347
slot_time_secs: KnownChain :: Holesky . slot_time_sec( ) ,
350
348
genesis_fork_version: KnownChain :: Holesky . genesis_fork_version( )
351
349
} )
@@ -360,11 +358,11 @@ mod tests {
360
358
path. pop ( ) ;
361
359
path. push ( "tests/data/sepolia_spec_data.json" ) ;
362
360
363
- let s = format ! ( "chain = {path:? }" ) ;
361
+ let s = format ! ( "chain = {{ genesis_time_secs = 1, path = {path:?}} }" ) ;
364
362
365
363
let decoded: MockConfig = toml:: from_str ( & s) . unwrap ( ) ;
366
364
assert_eq ! ( decoded. chain, Chain :: Custom {
367
- genesis_time_secs: KnownChain :: Sepolia . genesis_time_sec ( ) ,
365
+ genesis_time_secs: 1 ,
368
366
slot_time_secs: KnownChain :: Sepolia . slot_time_sec( ) ,
369
367
genesis_fork_version: KnownChain :: Sepolia . genesis_fork_version( )
370
368
} )
@@ -379,11 +377,11 @@ mod tests {
379
377
path. pop ( ) ;
380
378
path. push ( "tests/data/helder_spec.yml" ) ;
381
379
382
- let s = format ! ( "chain = {path:? }" ) ;
380
+ let s = format ! ( "chain = {{ genesis_time_secs = 1, path = {path:?}} }" ) ;
383
381
384
382
let decoded: MockConfig = toml:: from_str ( & s) . unwrap ( ) ;
385
383
assert_eq ! ( decoded. chain, Chain :: Custom {
386
- genesis_time_secs: KnownChain :: Helder . genesis_time_sec ( ) ,
384
+ genesis_time_secs: 1 ,
387
385
slot_time_secs: KnownChain :: Helder . slot_time_sec( ) ,
388
386
genesis_fork_version: KnownChain :: Helder . genesis_fork_version( )
389
387
} )
0 commit comments