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