1use cfx_bytes::Bytes;
6use cfx_internal_common::{ChainIdParams, ChainIdParamsInner};
7use cfx_parameters::{
8 block::{EVM_TRANSACTION_BLOCK_RATIO, EVM_TRANSACTION_GAS_RATIO},
9 consensus::{
10 CIP112_HEADER_CUSTOM_FIRST_ELEMENT,
11 DAO_VOTE_HEADER_CUSTOM_FIRST_ELEMENT,
12 NEXT_HARDFORK_HEADER_CUSTOM_FIRST_ELEMENT, ONE_UCFX_IN_DRIP,
13 TANZANITE_HEADER_CUSTOM_FIRST_ELEMENT,
14 },
15 consensus_internal::{
16 ANTICONE_PENALTY_RATIO, DAO_PARAMETER_VOTE_PERIOD,
17 INITIAL_BASE_MINING_REWARD_IN_UCFX,
18 },
19};
20use cfx_types::{AllChainID, Space, SpaceMap, U256, U512};
21use cfx_vm_types::{CIP645Spec, ConsensusGasSpec, Spec};
22use primitives::{block::BlockHeight, BlockNumber};
23use std::collections::BTreeMap;
24
25#[derive(Debug, Clone)]
30pub struct CommonParams {
31 pub maximum_extra_data_size: usize,
33 pub network_id: u64,
35 pub chain_id: ChainIdParams,
37 pub subprotocol_name: String,
39 pub min_gas_limit: U256,
41 pub gas_limit_bound_divisor: U256,
43 pub max_transaction_size: usize,
46 pub anticone_penalty_ratio: u64,
49 pub base_block_rewards: BTreeMap<BlockHeight, U256>,
51 pub evm_transaction_block_ratio: u64,
53 pub evm_transaction_gas_ratio: u64,
56 pub params_dao_vote_period: u64,
57 pub min_base_price: SpaceMap<U256>,
58
59 pub early_set_internal_contracts_states: bool,
62 pub transition_numbers: TransitionsBlockNumber,
64 pub transition_heights: TransitionsEpochHeight,
66 pub max_difficulty_guard: Option<U256>,
68 pub max_finalize_confirmation_guard: Option<u64>,
70}
71
72#[derive(Default, Debug, Clone)]
73pub struct TransitionsBlockNumber {
74 pub cip43a: BlockNumber,
76 pub cip43b: BlockNumber,
77 pub cip62: BlockNumber,
79 pub cip64: BlockNumber,
81 pub cip71: BlockNumber,
83 pub cip78a: BlockNumber,
85 pub cip78b: BlockNumber,
86 pub cip90b: BlockNumber,
88 pub cip92: BlockNumber,
90 pub cip94n: BlockNumber,
92 pub cip97: BlockNumber,
94 pub cip98: BlockNumber,
96 pub cip105: BlockNumber,
98 pub cip107: BlockNumber,
100 pub cip_sigma_fix: BlockNumber,
102 pub cip118: BlockNumber,
104 pub cip119: BlockNumber,
106 pub cip131: BlockNumber,
108 pub cip132: BlockNumber,
110 pub cip133b: BlockNumber,
112 pub cip137: BlockNumber,
114 pub cancun_opcodes: BlockNumber,
118 pub cip144: BlockNumber,
120 pub cip145: BlockNumber,
122}
123
124#[derive(Default, Debug, Clone)]
125pub struct TransitionsEpochHeight {
126 pub cip40: BlockHeight,
128 pub cip76: BlockHeight,
130 pub cip86: BlockHeight,
132 pub cip90a: BlockHeight,
134 pub cip94h: BlockHeight,
136 pub cip112: BlockHeight,
138 pub cip130: BlockHeight,
140 pub cip133e: BlockHeight,
142 pub cip1559: BlockHeight,
144 pub cip150: BlockHeight,
146 pub cip151: BlockHeight,
148 pub cip152: BlockHeight,
150 pub cip154: BlockHeight,
152 pub cip7702: BlockHeight,
154 pub cip645: BlockHeight,
156 pub align_evm: BlockHeight,
157 pub eip2935: BlockHeight,
159 pub eip2537: BlockHeight,
161 pub eip7623: BlockHeight,
163 pub cip_c2_fix: BlockHeight,
164 pub cip145_fix: BlockHeight,
165 pub cip166: BlockHeight,
167 pub cip167: BlockHeight,
169 pub cip172: BlockHeight,
172 pub cip174: BlockHeight,
175 pub cip175: BlockHeight,
177 pub cip176: BlockHeight,
179 pub cip_hn_fix: BlockHeight,
180}
181
182impl Default for CommonParams {
183 fn default() -> Self {
184 let mut base_block_rewards = BTreeMap::new();
185 base_block_rewards.insert(0, INITIAL_BASE_MINING_REWARD_IN_UCFX.into());
186 CommonParams {
187 maximum_extra_data_size: 0x20,
188 network_id: 0x1,
189 chain_id: ChainIdParamsInner::new_simple(AllChainID::new(1, 1)),
190 subprotocol_name: "cfx".into(),
191 min_gas_limit: 10_000_000.into(),
192 gas_limit_bound_divisor: 0x0400.into(),
193 max_transaction_size: 300 * 1024,
194 anticone_penalty_ratio: ANTICONE_PENALTY_RATIO,
195 base_block_rewards,
196 evm_transaction_block_ratio: EVM_TRANSACTION_BLOCK_RATIO,
197 evm_transaction_gas_ratio: EVM_TRANSACTION_GAS_RATIO,
198 params_dao_vote_period: DAO_PARAMETER_VOTE_PERIOD,
199 early_set_internal_contracts_states: false,
200 transition_numbers: Default::default(),
201 transition_heights: Default::default(),
202 min_base_price: SpaceMap::default(),
203 max_difficulty_guard: None,
204 max_finalize_confirmation_guard: None,
205 }
206 }
207}
208
209impl CommonParams {
210 pub fn spec(&self, number: BlockNumber, height: BlockHeight) -> Spec {
211 let mut spec = Spec::genesis_spec();
212 spec.cip43_contract = number >= self.transition_numbers.cip43a;
213 spec.cip43_init = number >= self.transition_numbers.cip43a
214 && number < self.transition_numbers.cip43b;
215 spec.cip62 = number >= self.transition_numbers.cip62;
216 spec.cip64 = number >= self.transition_numbers.cip64;
217 spec.cip71 = number >= self.transition_numbers.cip71;
218 spec.cip90 = number >= self.transition_numbers.cip90b;
219 spec.cip78a = number >= self.transition_numbers.cip78a;
220 spec.cip78b = number >= self.transition_numbers.cip78b;
221 spec.cip94 = number >= self.transition_numbers.cip94n;
222 spec.cip94_activation_block_number = self.transition_numbers.cip94n;
223 spec.cip97 = number >= self.transition_numbers.cip97;
224 spec.cip98 = number >= self.transition_numbers.cip98;
225 spec.cip105 = number >= self.transition_numbers.cip105;
226 spec.cip_sigma_fix = number >= self.transition_numbers.cip_sigma_fix;
227 spec.params_dao_vote_period = self.params_dao_vote_period;
228 spec.cip107 = number >= self.transition_numbers.cip107;
229 spec.cip118 = number >= self.transition_numbers.cip118;
230 spec.cip119 = number >= self.transition_numbers.cip119;
231 spec.cip131 = number >= self.transition_numbers.cip131;
232 spec.cip132 = number >= self.transition_numbers.cip132;
233 spec.cip133_b = self.transition_numbers.cip133b;
234 spec.cip133_e = self.transition_heights.cip133e;
235 spec.cip133_core = number >= self.transition_numbers.cip133b;
236 spec.cip137 = number >= self.transition_numbers.cip137;
237 spec.cip144 = number >= self.transition_numbers.cip144;
238 spec.cip145 = number >= self.transition_numbers.cip145;
239 spec.cip145_fix = height >= self.transition_heights.cip145_fix;
240 spec.cip1559 = height >= self.transition_heights.cip1559;
241 spec.cip150 = height >= self.transition_heights.cip150;
242 spec.cip151 = height >= self.transition_heights.cip151;
243 spec.cip152 = height >= self.transition_heights.cip152;
244 spec.cip154 = height >= self.transition_heights.cip154;
245 spec.cip7702 = height >= self.transition_heights.cip7702;
246 let cip645 = height >= self.transition_heights.cip645;
247 spec.cip645 = CIP645Spec::new(cip645);
248 spec.eip2935 = height >= self.transition_heights.eip2935;
249 spec.eip7623 = height >= self.transition_heights.eip7623;
250 spec.cip_c2_fix = height >= self.transition_heights.cip_c2_fix;
251 spec.cancun_opcodes = number >= self.transition_numbers.cancun_opcodes;
252 spec.align_evm = height >= self.transition_heights.align_evm && cip645;
253 spec.cip166 = height >= self.transition_heights.cip166;
254 spec.cip174 = height >= self.transition_heights.cip174;
255 spec.cip175 = height >= self.transition_heights.cip175;
256 spec.cip176 = height >= self.transition_heights.cip176;
257
258 spec.overwrite_gas_plan_by_cip();
259
260 spec
261 }
262
263 pub fn consensus_spec(&self, height: BlockHeight) -> ConsensusGasSpec {
264 let mut spec = ConsensusGasSpec::genesis_spec();
265 spec.cip1559 = height >= self.transition_heights.cip1559;
266 let cip645 = height >= self.transition_heights.cip645;
267 spec.cip645 = CIP645Spec::new(cip645);
268
269 spec.align_evm = height >= self.transition_heights.align_evm && cip645;
270
271 spec.overwrite_gas_plan_by_cip();
272
273 spec
274 }
275
276 #[cfg(test)]
277 pub fn spec_for_test(&self, number: u64) -> Spec {
278 self.spec(number, number)
279 }
280
281 pub fn base_reward_in_ucfx(
284 &self, _past_block_count: u64, height: BlockHeight,
285 ) -> U512 {
286 let (_, start_base_ward) = self.base_block_rewards.iter()
287 .rev()
288 .find(|&(block, _)| *block <= height)
289 .expect("Current block's reward is not found; this indicates a chain config error");
290 U512::from(start_base_ward) * U512::from(ONE_UCFX_IN_DRIP)
292 }
293
294 pub fn custom_prefix(&self, height: BlockHeight) -> Option<Vec<Bytes>> {
295 if height >= self.transition_heights.cip40
296 && height < self.transition_heights.cip94h
297 {
298 Some(vec![TANZANITE_HEADER_CUSTOM_FIRST_ELEMENT.to_vec()])
299 } else if height >= self.transition_heights.cip94h
300 && height < self.transition_heights.cip112
301 {
302 Some(vec![DAO_VOTE_HEADER_CUSTOM_FIRST_ELEMENT.to_vec()])
303 } else if height >= self.transition_heights.cip112
304 && height < self.transition_heights.cip1559
305 {
306 Some(vec![CIP112_HEADER_CUSTOM_FIRST_ELEMENT.to_vec()])
307 } else if height >= self.transition_heights.cip1559 {
308 Some(vec![NEXT_HARDFORK_HEADER_CUSTOM_FIRST_ELEMENT.to_vec()])
309 } else {
310 None
311 }
312 }
313
314 pub fn can_pack_evm_transaction(&self, height: BlockHeight) -> bool {
315 height % self.evm_transaction_block_ratio == 0
316 }
317
318 pub fn chain_id(&self, epoch_height: u64, space: Space) -> u32 {
319 self.chain_id
320 .read()
321 .get_chain_id(epoch_height)
322 .in_space(space)
323 }
324
325 pub fn chain_id_map(&self, epoch_height: u64) -> BTreeMap<Space, u32> {
326 BTreeMap::from([
327 (Space::Native, self.chain_id(epoch_height, Space::Native)),
328 (
329 Space::Ethereum,
330 self.chain_id(epoch_height, Space::Ethereum),
331 ),
332 ])
333 }
334
335 pub fn init_base_price(&self) -> SpaceMap<U256> { self.min_base_price }
336
337 pub fn min_base_price(&self) -> SpaceMap<U256> { self.min_base_price }
338}