espresso_types/v0/v0_3/
chain_config.rs1use crate::{v0_1, BlockSize, ChainId, FeeAccount, FeeAmount};
2use alloy::primitives::{Address, U256};
3use alloy_compat::ethers_serde;
4use committable::{Commitment, Committable};
5use itertools::Either;
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
10pub struct ChainConfig {
11 pub chain_id: ChainId,
13
14 pub max_block_size: BlockSize,
16
17 pub base_fee: FeeAmount,
19
20 #[serde(with = "ethers_serde::option_address")]
26 #[serde(default)]
27 pub fee_contract: Option<Address>,
28
29 pub fee_recipient: FeeAccount,
35
36 #[serde(with = "ethers_serde::option_address")]
42 #[serde(default)]
43 pub stake_table_contract: Option<Address>,
44}
45
46#[derive(Clone, Debug, Copy, PartialEq, Deserialize, Serialize, Eq, Hash)]
47pub struct ResolvableChainConfig {
48 pub(crate) chain_config: Either<ChainConfig, Commitment<ChainConfig>>,
49}
50
51impl Committable for ChainConfig {
52 fn tag() -> String {
53 "CHAIN_CONFIG".to_string()
54 }
55
56 fn commit(&self) -> Commitment<Self> {
57 let comm = committable::RawCommitmentBuilder::new(&Self::tag())
58 .fixed_size_field("chain_id", &self.chain_id.to_fixed_bytes())
59 .u64_field("max_block_size", *self.max_block_size)
60 .fixed_size_field("base_fee", &self.base_fee.to_fixed_bytes())
61 .fixed_size_field("fee_recipient", &self.fee_recipient.to_fixed_bytes());
62 let comm = if let Some(addr) = self.fee_contract {
63 comm.u64_field("fee_contract", 1).fixed_size_bytes(&addr.0)
64 } else {
65 comm.u64_field("fee_contract", 0)
66 };
67 let comm = if let Some(addr) = self.stake_table_contract {
71 comm.u64_field("stake_table_contract", 1)
72 .fixed_size_bytes(&addr.0)
73 } else {
74 comm
75 };
76
77 comm.finalize()
78 }
79}
80
81impl ResolvableChainConfig {
82 pub fn commit(&self) -> Commitment<ChainConfig> {
83 match self.chain_config {
84 Either::Left(config) => config.commit(),
85 Either::Right(commitment) => commitment,
86 }
87 }
88 pub fn resolve(self) -> Option<ChainConfig> {
89 match self.chain_config {
90 Either::Left(config) => Some(config),
91 Either::Right(_) => None,
92 }
93 }
94}
95
96impl From<Commitment<ChainConfig>> for ResolvableChainConfig {
97 fn from(value: Commitment<ChainConfig>) -> Self {
98 Self {
99 chain_config: Either::Right(value),
100 }
101 }
102}
103
104impl From<ChainConfig> for ResolvableChainConfig {
105 fn from(value: ChainConfig) -> Self {
106 Self {
107 chain_config: Either::Left(value),
108 }
109 }
110}
111
112impl From<&v0_1::ResolvableChainConfig> for ResolvableChainConfig {
113 fn from(
114 &v0_1::ResolvableChainConfig { chain_config }: &v0_1::ResolvableChainConfig,
115 ) -> ResolvableChainConfig {
116 match chain_config {
117 Either::Left(chain_config) => ResolvableChainConfig {
118 chain_config: Either::Left(ChainConfig::from(chain_config)),
119 },
120 Either::Right(c) => ResolvableChainConfig {
121 chain_config: Either::Right(Commitment::from_raw(*c.as_ref())),
122 },
123 }
124 }
125}
126
127impl From<v0_1::ChainConfig> for ChainConfig {
128 fn from(chain_config: v0_1::ChainConfig) -> ChainConfig {
129 let v0_1::ChainConfig {
130 chain_id,
131 max_block_size,
132 base_fee,
133 fee_contract,
134 fee_recipient,
135 ..
136 } = chain_config;
137
138 ChainConfig {
139 chain_id,
140 max_block_size,
141 base_fee,
142 fee_contract,
143 fee_recipient,
144 stake_table_contract: None,
145 }
146 }
147}
148
149
150
151impl From<ChainConfig> for v0_1::ChainConfig {
152 fn from(chain_config: ChainConfig) -> v0_1::ChainConfig {
153 let ChainConfig {
154 chain_id,
155 max_block_size,
156 base_fee,
157 fee_contract,
158 fee_recipient,
159 ..
160 } = chain_config;
161
162 v0_1::ChainConfig {
163 chain_id,
164 max_block_size,
165 base_fee,
166 fee_contract,
167 fee_recipient,
168 }
169 }
170}
171
172impl Default for ChainConfig {
173 fn default() -> Self {
174 Self {
175 chain_id: U256::from(35353).into(), max_block_size: 30720.into(),
177 base_fee: 0.into(),
178 fee_contract: None,
179 fee_recipient: Default::default(),
180 stake_table_contract: None,
181 }
182 }
183}
184
185
186#[cfg(test)]
187mod test {
188 use super::*;
189
190 #[test]
191 fn test_upgrade_chain_config_v3_resolvable_chain_config_from_v1() {
192 let expectation: ResolvableChainConfig = ChainConfig::default().into();
193 let v1_resolvable: v0_1::ResolvableChainConfig = v0_1::ChainConfig::default().into();
194 let v3_resolvable: ResolvableChainConfig = ResolvableChainConfig::from(&v1_resolvable);
195 assert_eq!(expectation, v3_resolvable);
196 let expectation: ResolvableChainConfig = ChainConfig::default().commit().into();
197 let v1_resolvable: v0_1::ResolvableChainConfig =
198 v0_1::ChainConfig::default().commit().into();
199 let v3_resolvable: ResolvableChainConfig = ResolvableChainConfig::from(&v1_resolvable);
200 assert_eq!(expectation, v3_resolvable);
201 }
202
203
204
205 #[test]
206 fn test_upgrade_chain_config_v1_chain_config_from_v3() {
207 let expectation = v0_1::ChainConfig::default();
208 let v3_chain_config = ChainConfig::default();
209 let v1_chain_config = v0_1::ChainConfig::from(v3_chain_config);
210 assert_eq!(expectation, v1_chain_config);
211 }
212
213
214}