|
1 | | -use eth_config_api::{EthConfigResponse, ForkConfig}; |
| 1 | +use eth_config_api::{EthConfigResponse, ForkConfig, ForkId}; |
2 | 2 |
|
3 | 3 | /// Resolves fork configuration from a chain specification at runtime. |
4 | 4 | /// |
5 | 5 | /// Reth plumbing will populate this with access to `ChainSpec` and consensus params; the logic |
6 | 6 | /// belongs here so it can be tested separately from RPC wiring. |
7 | | -#[derive(Debug, Default)] |
8 | | -pub struct ForkConfigResolver; |
| 7 | +#[derive(Debug, Clone)] |
| 8 | +pub struct ForkConfigResolver { |
| 9 | + genesis_hash: [u8; 32], |
| 10 | + forks: Vec<ForkConfig>, |
| 11 | +} |
9 | 12 |
|
10 | 13 | impl ForkConfigResolver { |
11 | | - /// Create a new resolver (wire in reth chain spec later). |
12 | | - pub fn new() -> Self { |
13 | | - Self |
| 14 | + /// Create a new resolver with a pre-resolved fork list and genesis hash. |
| 15 | + pub fn new(genesis_hash: [u8; 32], mut forks: Vec<ForkConfig>) -> Self { |
| 16 | + forks.sort_by_key(|f| f.block.map(|b| b.0).unwrap_or(u64::MAX)); |
| 17 | + Self { genesis_hash, forks } |
14 | 18 | } |
15 | 19 |
|
16 | 20 | /// Compute eth_config response for the provided block height. |
17 | | - pub fn resolve_at_block(&self, _block_number: u64) -> EthConfigResponse { |
18 | | - // Placeholder implementation; real logic will derive current/next/last forks, |
19 | | - // blob parameters, precompiles, system contracts, and fork id. |
20 | | - let placeholder = ForkConfig { |
21 | | - name: "placeholder".into(), |
22 | | - block: Some(_block_number), |
23 | | - blob_schedule: None, |
24 | | - precompiles: vec![], |
25 | | - system_contracts: vec![], |
26 | | - }; |
| 21 | + pub fn resolve_at_block(&self, block_number: u64) -> EthConfigResponse { |
| 22 | + let mut current: Option<ForkConfig> = None; |
| 23 | + let mut last: Option<ForkConfig> = None; |
| 24 | + let mut next: Option<ForkConfig> = None; |
| 25 | + |
| 26 | + for fork in &self.forks { |
| 27 | + let fork_block = fork.block.map(|b| b.0).unwrap_or(u64::MAX); |
| 28 | + if fork_block <= block_number { |
| 29 | + last = current.replace(fork.clone()); |
| 30 | + continue; |
| 31 | + } |
| 32 | + next = Some(fork.clone()); |
| 33 | + break; |
| 34 | + } |
| 35 | + |
| 36 | + let current = current.unwrap_or_else(|| self.forks.first().cloned().unwrap_or_default()); |
| 37 | + |
| 38 | + let fork_blocks: Vec<u64> = self |
| 39 | + .forks |
| 40 | + .iter() |
| 41 | + .filter_map(|f| f.block.map(|b| b.0)) |
| 42 | + .filter(|b| *b <= block_number) |
| 43 | + .collect(); |
| 44 | + |
| 45 | + let fork_id = ForkId::compute( |
| 46 | + self.genesis_hash, |
| 47 | + &fork_blocks, |
| 48 | + next.as_ref().and_then(|f| f.block.map(|b| b.0)), |
| 49 | + ); |
27 | 50 |
|
28 | 51 | EthConfigResponse { |
29 | | - current: eth_config_api::types::ForkEntry { |
30 | | - config: placeholder, |
31 | | - }, |
32 | | - next: None, |
33 | | - last: None, |
34 | | - fork_id: eth_config_api::ForkId::placeholder(), |
| 52 | + current, |
| 53 | + next, |
| 54 | + last, |
| 55 | + fork_id, |
35 | 56 | } |
36 | 57 | } |
37 | 58 | } |
0 commit comments