use cfx_bytes::Bytes;
use cfx_internal_common::{ChainIdParams, ChainIdParamsInner};
use cfx_parameters::{
block::{EVM_TRANSACTION_BLOCK_RATIO, EVM_TRANSACTION_GAS_RATIO},
consensus::{
CIP112_HEADER_CUSTOM_FIRST_ELEMENT,
DAO_VOTE_HEADER_CUSTOM_FIRST_ELEMENT,
NEXT_HARDFORK_HEADER_CUSTOM_FIRST_ELEMENT, ONE_UCFX_IN_DRIP,
TANZANITE_HEADER_CUSTOM_FIRST_ELEMENT,
},
consensus_internal::{
ANTICONE_PENALTY_RATIO, DAO_PARAMETER_VOTE_PERIOD,
INITIAL_BASE_MINING_REWARD_IN_UCFX,
},
};
use cfx_types::{AllChainID, Space, SpaceMap, U256, U512};
use cfx_vm_types::Spec;
use primitives::{block::BlockHeight, BlockNumber};
use std::collections::BTreeMap;
#[derive(Debug, Clone)]
pub struct CommonParams {
pub maximum_extra_data_size: usize,
pub network_id: u64,
pub chain_id: ChainIdParams,
pub subprotocol_name: String,
pub min_gas_limit: U256,
pub gas_limit_bound_divisor: U256,
pub max_transaction_size: usize,
pub anticone_penalty_ratio: u64,
pub base_block_rewards: BTreeMap<BlockHeight, U256>,
pub evm_transaction_block_ratio: u64,
pub evm_transaction_gas_ratio: u64,
pub params_dao_vote_period: u64,
pub min_base_price: SpaceMap<U256>,
pub early_set_internal_contracts_states: bool,
pub transition_numbers: TransitionsBlockNumber,
pub transition_heights: TransitionsEpochHeight,
}
#[derive(Default, Debug, Clone)]
pub struct TransitionsBlockNumber {
pub cip43a: BlockNumber,
pub cip43b: BlockNumber,
pub cip62: BlockNumber,
pub cip64: BlockNumber,
pub cip71: BlockNumber,
pub cip78a: BlockNumber,
pub cip78b: BlockNumber,
pub cip90b: BlockNumber,
pub cip92: BlockNumber,
pub cip94n: BlockNumber,
pub cip97: BlockNumber,
pub cip98: BlockNumber,
pub cip105: BlockNumber,
pub cip107: BlockNumber,
pub cip_sigma_fix: BlockNumber,
pub cip118: BlockNumber,
pub cip119: BlockNumber,
pub cip131: BlockNumber,
pub cip132: BlockNumber,
pub cip133b: BlockNumber,
pub cip137: BlockNumber,
pub cancun_opcodes: BlockNumber,
pub cip144: BlockNumber,
pub cip145: BlockNumber,
}
#[derive(Default, Debug, Clone)]
pub struct TransitionsEpochHeight {
pub cip40: BlockHeight,
pub cip76: BlockHeight,
pub cip86: BlockHeight,
pub cip90a: BlockHeight,
pub cip94h: BlockHeight,
pub cip112: BlockHeight,
pub cip130: BlockHeight,
pub cip133e: BlockHeight,
pub cip1559: BlockHeight,
}
impl Default for CommonParams {
fn default() -> Self {
let mut base_block_rewards = BTreeMap::new();
base_block_rewards.insert(0, INITIAL_BASE_MINING_REWARD_IN_UCFX.into());
CommonParams {
maximum_extra_data_size: 0x20,
network_id: 0x1,
chain_id: ChainIdParamsInner::new_simple(AllChainID::new(1, 1)),
subprotocol_name: "cfx".into(),
min_gas_limit: 10_000_000.into(),
gas_limit_bound_divisor: 0x0400.into(),
max_transaction_size: 300 * 1024,
anticone_penalty_ratio: ANTICONE_PENALTY_RATIO,
base_block_rewards,
evm_transaction_block_ratio: EVM_TRANSACTION_BLOCK_RATIO,
evm_transaction_gas_ratio: EVM_TRANSACTION_GAS_RATIO,
params_dao_vote_period: DAO_PARAMETER_VOTE_PERIOD,
early_set_internal_contracts_states: false,
transition_numbers: Default::default(),
transition_heights: Default::default(),
min_base_price: SpaceMap::default(),
}
}
}
impl CommonParams {
pub fn spec(&self, number: BlockNumber, height: BlockHeight) -> Spec {
let mut spec = Spec::genesis_spec();
spec.cip43_contract = number >= self.transition_numbers.cip43a;
spec.cip43_init = number >= self.transition_numbers.cip43a
&& number < self.transition_numbers.cip43b;
spec.cip62 = number >= self.transition_numbers.cip62;
spec.cip64 = number >= self.transition_numbers.cip64;
spec.cip71 = number >= self.transition_numbers.cip71;
spec.cip90 = number >= self.transition_numbers.cip90b;
spec.cip78a = number >= self.transition_numbers.cip78a;
spec.cip78b = number >= self.transition_numbers.cip78b;
spec.cip94 = number >= self.transition_numbers.cip94n;
spec.cip94_activation_block_number = self.transition_numbers.cip94n;
spec.cip97 = number >= self.transition_numbers.cip97;
spec.cip98 = number >= self.transition_numbers.cip98;
spec.cip105 = number >= self.transition_numbers.cip105;
spec.cip_sigma_fix = number >= self.transition_numbers.cip_sigma_fix;
spec.params_dao_vote_period = self.params_dao_vote_period;
spec.cip107 = number >= self.transition_numbers.cip107;
spec.cip118 = number >= self.transition_numbers.cip118;
spec.cip119 = number >= self.transition_numbers.cip119;
spec.cip131 = number >= self.transition_numbers.cip131;
spec.cip132 = number >= self.transition_numbers.cip132;
spec.cip133_b = self.transition_numbers.cip133b;
spec.cip133_e = self.transition_heights.cip133e;
spec.cip133_core = number >= self.transition_numbers.cip133b;
spec.cip137 = number >= self.transition_numbers.cip137;
spec.cip144 = number >= self.transition_numbers.cip144;
spec.cip145 = number >= self.transition_numbers.cip145;
spec.cip1559 = height >= self.transition_heights.cip1559;
spec.cancun_opcodes = number >= self.transition_numbers.cancun_opcodes;
if spec.cancun_opcodes {
spec.sload_gas = 800;
}
spec
}
#[cfg(test)]
pub fn spec_for_test(&self, number: u64) -> Spec {
self.spec(number, number)
}
pub fn base_reward_in_ucfx(
&self, _past_block_count: u64, height: BlockHeight,
) -> U512 {
let (_, start_base_ward) = self.base_block_rewards.iter()
.rev()
.find(|&(block, _)| *block <= height)
.expect("Current block's reward is not found; this indicates a chain config error");
U512::from(start_base_ward) * U512::from(ONE_UCFX_IN_DRIP)
}
pub fn custom_prefix(&self, height: BlockHeight) -> Option<Vec<Bytes>> {
if height >= self.transition_heights.cip40
&& height < self.transition_heights.cip94h
{
Some(vec![TANZANITE_HEADER_CUSTOM_FIRST_ELEMENT.to_vec()])
} else if height >= self.transition_heights.cip94h
&& height < self.transition_heights.cip112
{
Some(vec![DAO_VOTE_HEADER_CUSTOM_FIRST_ELEMENT.to_vec()])
} else if height >= self.transition_heights.cip112
&& height < self.transition_heights.cip1559
{
Some(vec![CIP112_HEADER_CUSTOM_FIRST_ELEMENT.to_vec()])
} else if height >= self.transition_heights.cip1559 {
Some(vec![NEXT_HARDFORK_HEADER_CUSTOM_FIRST_ELEMENT.to_vec()])
} else {
None
}
}
pub fn can_pack_evm_transaction(&self, height: BlockHeight) -> bool {
height % self.evm_transaction_block_ratio == 0
}
pub fn chain_id(&self, epoch_height: u64, space: Space) -> u32 {
self.chain_id
.read()
.get_chain_id(epoch_height)
.in_space(space)
}
pub fn chain_id_map(&self, epoch_height: u64) -> BTreeMap<Space, u32> {
BTreeMap::from([
(Space::Native, self.chain_id(epoch_height, Space::Native)),
(
Space::Ethereum,
self.chain_id(epoch_height, Space::Ethereum),
),
])
}
pub fn init_base_price(&self) -> SpaceMap<U256> { self.min_base_price }
pub fn min_base_price(&self) -> SpaceMap<U256> { self.min_base_price }
}