Skip to content

Commit 036b2e9

Browse files
committed
add genesis time in path chain loader
1 parent 75e8129 commit 036b2e9

File tree

4 files changed

+66
-47
lines changed

4 files changed

+66
-47
lines changed

config.example.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
# Chain spec ID. Supported values:
55
# A network ID. Supported values: Mainnet, Holesky, Sepolia, Helder.
6-
# A path to a chain spec file, either in .json format (e.g., as returned by the beacon endpoint /eth/v1/config/spec), or in .yml format (see examples in tests/data).
6+
# A custom object, e.g., chain = { genesis_time_secs = 1695902400, path = "/path/to/spec.json" }, with a path to a chain spec file, either in .json format (e.g., as returned by the beacon endpoint /eth/v1/config/spec), or in .yml format (see examples in tests/data).
77
# A custom object, e.g., chain = { genesis_time_secs = 1695902400, slot_time_secs = 12, genesis_fork_version = "0x01017000" }.
88
chain = "Holesky"
99

configs/custom_chain.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# PBS config with a custom chain spec file
2+
3+
# genesis time in seconds needs to be specified
4+
chain = { genesis_time_secs = 100, path = "tests/data/holesky_spec.json" }
5+
6+
[pbs]
7+
port = 18550
8+
9+
[[relays]]
10+
id = "example-relay"
11+
url = "http://0xa1cec75a3f0661e99299274182938151e8433c61a19222347ea1313d839229cb4ce4e3e5aa2bdeb71c8fcf1b084963c2@abc.xyz"

crates/common/src/config/mod.rs

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -48,22 +48,34 @@ impl CommitBoostConfig {
4848
// When loading the config from the environment, it's important that every path
4949
// is replaced with the correct value if the config is loaded inside a container
5050
pub fn from_env_path() -> Result<Self> {
51-
let config = if let Some(path) = load_optional_env_var(CHAIN_SPEC_ENV) {
52-
// if the chain spec file is set, load it separately
53-
let chain: Chain = load_chain_from_file(path.parse()?)?;
54-
let rest_config: HelperConfig = load_file_from_env(CONFIG_ENV)?;
51+
let helper_config: HelperConfig = load_file_from_env(CONFIG_ENV)?;
5552

56-
CommitBoostConfig {
57-
chain,
58-
relays: rest_config.relays,
59-
pbs: rest_config.pbs,
60-
modules: rest_config.modules,
61-
signer: rest_config.signer,
62-
metrics: rest_config.metrics,
63-
logs: rest_config.logs,
53+
let chain = match helper_config.chain {
54+
ChainLoader::Path { path, genesis_time_secs } => {
55+
// check if the file path is overridden by env var
56+
let (slot_time_secs, genesis_fork_version) =
57+
if let Some(path) = load_optional_env_var(CHAIN_SPEC_ENV) {
58+
load_chain_from_file(path.parse()?)?
59+
} else {
60+
load_chain_from_file(path)?
61+
};
62+
Chain::Custom { genesis_time_secs, slot_time_secs, genesis_fork_version }
6463
}
65-
} else {
66-
load_file_from_env(CONFIG_ENV)?
64+
ChainLoader::Known(known) => Chain::from(known),
65+
ChainLoader::Custom { genesis_time_secs, slot_time_secs, genesis_fork_version } => {
66+
let genesis_fork_version: [u8; 4] = genesis_fork_version.as_ref().try_into()?;
67+
Chain::Custom { genesis_time_secs, slot_time_secs, genesis_fork_version }
68+
}
69+
};
70+
71+
let config = CommitBoostConfig {
72+
chain,
73+
relays: helper_config.relays,
74+
pbs: helper_config.pbs,
75+
modules: helper_config.modules,
76+
signer: helper_config.signer,
77+
metrics: helper_config.metrics,
78+
logs: helper_config.logs,
6779
};
6880

6981
config.validate()?;
@@ -74,8 +86,8 @@ impl CommitBoostConfig {
7486
pub fn chain_spec_file(path: &str) -> Option<PathBuf> {
7587
match load_from_file::<ChainConfig>(path) {
7688
Ok(config) => {
77-
if let ChainLoader::Path(path_buf) = config.chain {
78-
Some(path_buf)
89+
if let ChainLoader::Path { path, genesis_time_secs: _ } = config.chain {
90+
Some(path)
7991
} else {
8092
None
8193
}
@@ -94,6 +106,7 @@ struct ChainConfig {
94106
/// Helper struct to load the rest of the config
95107
#[derive(Deserialize)]
96108
struct HelperConfig {
109+
chain: ChainLoader,
97110
relays: Vec<RelayConfig>,
98111
pbs: StaticPbsConfig,
99112
modules: Option<Vec<StaticModuleConfig>>,

crates/common/src/types.rs

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,19 @@ impl From<KnownChain> for Chain {
163163
#[serde(untagged)]
164164
pub enum ChainLoader {
165165
Known(KnownChain),
166-
Path(PathBuf),
167-
Custom { genesis_time_secs: u64, slot_time_secs: u64, genesis_fork_version: Bytes },
166+
Path {
167+
/// Genesis time as returned in /eth/v1/beacon/genesis
168+
genesis_time_secs: u64,
169+
/// Path to the genesis spec, as returned by /eth/v1/config/spec
170+
/// either in JSON or YAML format
171+
path: PathBuf,
172+
},
173+
Custom {
174+
/// Genesis time as returned in /eth/v1/beacon/genesis
175+
genesis_time_secs: u64,
176+
slot_time_secs: u64,
177+
genesis_fork_version: Bytes,
178+
},
168179
}
169180

170181
impl Serialize for Chain {
@@ -199,7 +210,11 @@ impl<'de> Deserialize<'de> for Chain {
199210

200211
match loader {
201212
ChainLoader::Known(known) => Ok(Chain::from(known)),
202-
ChainLoader::Path(path) => load_chain_from_file(path).map_err(serde::de::Error::custom),
213+
ChainLoader::Path { genesis_time_secs, path } => {
214+
let (slot_time_secs, genesis_fork_version) =
215+
load_chain_from_file(path).map_err(serde::de::Error::custom)?;
216+
Ok(Chain::Custom { genesis_time_secs, slot_time_secs, genesis_fork_version })
217+
}
203218
ChainLoader::Custom { genesis_time_secs, slot_time_secs, genesis_fork_version } => {
204219
let genesis_fork_version: [u8; 4] =
205220
genesis_fork_version.as_ref().try_into().map_err(serde::de::Error::custom)?;
@@ -209,38 +224,25 @@ impl<'de> Deserialize<'de> for Chain {
209224
}
210225
}
211226

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
227+
/// Returns seconds_per_slot and genesis_fork_version from a spec, such as
228+
/// returned by /eth/v1/config/spec ref: https://ethereum.github.io/beacon-APIs/#/Config/getSpec
214229
/// Try to load two formats:
215230
/// - JSON as return the getSpec endpoint, either with or without the `data`
216231
/// field
217232
/// - YAML as used e.g. in Kurtosis/Ethereum Package
218-
pub fn load_chain_from_file(path: PathBuf) -> eyre::Result<Chain> {
233+
pub fn load_chain_from_file(path: PathBuf) -> eyre::Result<(u64, [u8; 4])> {
219234
#[derive(Deserialize)]
220235
#[serde(rename_all = "UPPERCASE")]
221236
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,
226237
#[serde(with = "serde_utils::quoted_u64")]
227238
seconds_per_slot: u64,
228239
genesis_fork_version: Bytes,
229240
}
230241

231242
impl QuotedSpecFile {
232-
fn to_chain(&self) -> eyre::Result<Chain> {
243+
fn to_chain(&self) -> eyre::Result<(u64, [u8; 4])> {
233244
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+
Ok((self.seconds_per_slot, genesis_fork_version))
244246
}
245247
}
246248

@@ -252,21 +254,14 @@ pub fn load_chain_from_file(path: PathBuf) -> eyre::Result<Chain> {
252254
#[derive(Deserialize)]
253255
#[serde(rename_all = "UPPERCASE")]
254256
struct SpecFile {
255-
min_genesis_time: u64,
256-
genesis_delay: u64,
257257
seconds_per_slot: u64,
258258
genesis_fork_version: u32,
259259
}
260260

261261
impl SpecFile {
262-
fn to_chain(&self) -> Chain {
262+
fn to_chain(&self) -> (u64, [u8; 4]) {
263263
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-
}
264+
(self.seconds_per_slot, genesis_fork_version)
270265
}
271266
}
272267

0 commit comments

Comments
 (0)