cfx_executor/
spec.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5use 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// FIXME: This type is mainly used for execution layer parameters, but some
26// consensus layer parameters and functions are also inappropriately placed
27// here.
28
29#[derive(Debug, Clone)]
30pub struct CommonParams {
31    /// Maximum size of extra data.
32    pub maximum_extra_data_size: usize,
33    /// Network id.
34    pub network_id: u64,
35    /// Chain id.
36    pub chain_id: ChainIdParams,
37    /// Main subprotocol name.
38    pub subprotocol_name: String,
39    /// Minimum gas limit.
40    pub min_gas_limit: U256,
41    /// Gas limit bound divisor (how much gas limit can change per block)
42    pub gas_limit_bound_divisor: U256,
43    /// Number of first block where max code size limit is active.
44    /// Maximum size of transaction's RLP payload.
45    pub max_transaction_size: usize,
46    /// Anticone penalty ratio for reward processing.
47    /// It should be less than `timer_chain_beta`.
48    pub anticone_penalty_ratio: u64,
49    /// Initial base rewards according to block height.
50    pub base_block_rewards: BTreeMap<BlockHeight, U256>,
51    /// The ratio of blocks in the EVM transactions
52    pub evm_transaction_block_ratio: u64,
53    /// The gas ratio of evm transactions for the block can pack the EVM
54    /// transactions
55    pub evm_transaction_gas_ratio: u64,
56    pub params_dao_vote_period: u64,
57    pub min_base_price: SpaceMap<U256>,
58
59    /// Set the internal contracts to state at the genesis blocks, even if it
60    /// is not activated.
61    pub early_set_internal_contracts_states: bool,
62    /// The upgrades activated at given block number.
63    pub transition_numbers: TransitionsBlockNumber,
64    /// The upgrades activated at given block height (a.k.a. epoch number).
65    pub transition_heights: TransitionsEpochHeight,
66}
67
68#[derive(Default, Debug, Clone)]
69pub struct TransitionsBlockNumber {
70    /// CIP-43: Introduce Finality Through Staking Vote
71    pub cip43a: BlockNumber,
72    pub cip43b: BlockNumber,
73    /// CIP-62: Enable EC-Related Builtin Contracts
74    pub cip62: BlockNumber,
75    /// CIP-64: Get Current Epoch Number via Internal Contract
76    pub cip64: BlockNumber,
77    /// CIP-71: Disable Anti-Reentrancy
78    pub cip71: BlockNumber,
79    /// CIP-78: Correct `is_sponsored` Fields in Receipt
80    pub cip78a: BlockNumber,
81    pub cip78b: BlockNumber,
82    /// CIP-90: Introduce a Fully EVM-Compatible Space
83    pub cip90b: BlockNumber,
84    /// CIP-92: Enable Blake2F Builtin Function
85    pub cip92: BlockNumber,
86    /// CIP-94: On-Chain DAO Vote for Chain Parameters
87    pub cip94n: BlockNumber,
88    /// CIP-97: Clear Staking Lists
89    pub cip97: BlockNumber,
90    /// CIP-98: Fix BLOCKHASH Opcode Bug in eSpace
91    pub cip98: BlockNumber,
92    /// CIP-105: Minimal DAO Vote Count Based on PoS Staking
93    pub cip105: BlockNumber,
94    /// CIP-107: DAO-Adjustable Burn of Storage Collateral
95    pub cip107: BlockNumber,
96    /// A security fix without a publicly submitted CIP
97    pub cip_sigma_fix: BlockNumber,
98    /// CIP-118: Query Unused Storage Points in Internal Contract
99    pub cip118: BlockNumber,
100    /// CIP-119: PUSH0 instruction
101    pub cip119: BlockNumber,
102    /// CIP-131: Retain Whitelist on Contract Deletion
103    pub cip131: BlockNumber,
104    /// CIP-132: Fix Static Context Check for Internal Contracts
105    pub cip132: BlockNumber,
106    /// CIP-133: Enhanced Block Hash Query
107    pub cip133b: BlockNumber,
108    /// CIP-137: Base Fee Sharing in CIP-1559
109    pub cip137: BlockNumber,
110    /// CIP-141: Disable Subroutine Opcodes
111    /// CIP-142: Transient Storage Opcodes
112    /// CIP-143: MCOPY (0x5e) Opcode for Efficient Memory Copy
113    pub cancun_opcodes: BlockNumber,
114    /// CIP-144: Point Evaluation Precompile from EIP-4844
115    pub cip144: BlockNumber,
116    /// CIP-145: Fix Receipts upon `NotEnoughBalance` Error
117    pub cip145: BlockNumber,
118}
119
120#[derive(Default, Debug, Clone)]
121pub struct TransitionsEpochHeight {
122    /// CIP-40: Reduce Block Base Reward to 2 CFX
123    pub cip40: BlockHeight,
124    /// CIP-76: Remove VM-Related Constraints in Syncing Blocks
125    pub cip76: BlockHeight,
126    /// CIP-86: Update Difficulty Adjustment Algorithm
127    pub cip86: BlockHeight,
128    /// CIP-90: Introduce a Fully EVM-Compatible Space
129    pub cip90a: BlockHeight,
130    /// CIP-94: On-Chain DAO Vote for Chain Parameters
131    pub cip94h: BlockHeight,
132    /// CIP-112: Fix Block Headers `custom` Field Serde
133    pub cip112: BlockHeight,
134    /// CIP-130: Aligning Gas Limit with Transaction Size
135    pub cip130: BlockHeight,
136    /// CIP-133: Enhanced Block Hash Query
137    pub cip133e: BlockHeight,
138    /// CIP-1559: Fee Market Change for Conflux
139    pub cip1559: BlockHeight,
140    /// CIP-150: Reject New Contract Code Starting with the 0xEF byte
141    pub cip150: BlockHeight,
142    /// CIP-151: SELFDESTRUCT only in Same Transaction
143    pub cip151: BlockHeight,
144    /// CIP-152: Reject Transactions from Senders with Deployed Code
145    pub cip152: BlockHeight,
146    /// CIP-154: Fix Inconsistent Implementation of TLOAD
147    pub cip154: BlockHeight,
148    /// CIP-7702: Set Code for EOA
149    pub cip7702: BlockHeight,
150    /// CIP-645: Align Conflux Gas Pricing with EVM
151    pub cip645: BlockHeight,
152    pub align_evm: BlockHeight,
153    /// EIP-2935: Serve historical block hashes from state
154    pub eip2935: BlockHeight,
155    /// EIP-2537: Precompile for BLS12-381 curve operations
156    pub eip2537: BlockHeight,
157    /// EIP-7623: Increase calldata cost
158    pub eip7623: BlockHeight,
159    pub cip_c2_fix: BlockHeight,
160    pub cip145_fix: BlockHeight,
161    /// EIP-7939: Count Leading Zeros Instruction
162    pub cip166: BlockHeight,
163}
164
165impl Default for CommonParams {
166    fn default() -> Self {
167        let mut base_block_rewards = BTreeMap::new();
168        base_block_rewards.insert(0, INITIAL_BASE_MINING_REWARD_IN_UCFX.into());
169        CommonParams {
170            maximum_extra_data_size: 0x20,
171            network_id: 0x1,
172            chain_id: ChainIdParamsInner::new_simple(AllChainID::new(1, 1)),
173            subprotocol_name: "cfx".into(),
174            min_gas_limit: 10_000_000.into(),
175            gas_limit_bound_divisor: 0x0400.into(),
176            max_transaction_size: 300 * 1024,
177            anticone_penalty_ratio: ANTICONE_PENALTY_RATIO,
178            base_block_rewards,
179            evm_transaction_block_ratio: EVM_TRANSACTION_BLOCK_RATIO,
180            evm_transaction_gas_ratio: EVM_TRANSACTION_GAS_RATIO,
181            params_dao_vote_period: DAO_PARAMETER_VOTE_PERIOD,
182            early_set_internal_contracts_states: false,
183            transition_numbers: Default::default(),
184            transition_heights: Default::default(),
185            min_base_price: SpaceMap::default(),
186        }
187    }
188}
189
190impl CommonParams {
191    pub fn spec(&self, number: BlockNumber, height: BlockHeight) -> Spec {
192        let mut spec = Spec::genesis_spec();
193        spec.cip43_contract = number >= self.transition_numbers.cip43a;
194        spec.cip43_init = number >= self.transition_numbers.cip43a
195            && number < self.transition_numbers.cip43b;
196        spec.cip62 = number >= self.transition_numbers.cip62;
197        spec.cip64 = number >= self.transition_numbers.cip64;
198        spec.cip71 = number >= self.transition_numbers.cip71;
199        spec.cip90 = number >= self.transition_numbers.cip90b;
200        spec.cip78a = number >= self.transition_numbers.cip78a;
201        spec.cip78b = number >= self.transition_numbers.cip78b;
202        spec.cip94 = number >= self.transition_numbers.cip94n;
203        spec.cip94_activation_block_number = self.transition_numbers.cip94n;
204        spec.cip97 = number >= self.transition_numbers.cip97;
205        spec.cip98 = number >= self.transition_numbers.cip98;
206        spec.cip105 = number >= self.transition_numbers.cip105;
207        spec.cip_sigma_fix = number >= self.transition_numbers.cip_sigma_fix;
208        spec.params_dao_vote_period = self.params_dao_vote_period;
209        spec.cip107 = number >= self.transition_numbers.cip107;
210        spec.cip118 = number >= self.transition_numbers.cip118;
211        spec.cip119 = number >= self.transition_numbers.cip119;
212        spec.cip131 = number >= self.transition_numbers.cip131;
213        spec.cip132 = number >= self.transition_numbers.cip132;
214        spec.cip133_b = self.transition_numbers.cip133b;
215        spec.cip133_e = self.transition_heights.cip133e;
216        spec.cip133_core = number >= self.transition_numbers.cip133b;
217        spec.cip137 = number >= self.transition_numbers.cip137;
218        spec.cip144 = number >= self.transition_numbers.cip144;
219        spec.cip145 = number >= self.transition_numbers.cip145;
220        spec.cip145_fix = height >= self.transition_heights.cip145_fix;
221        spec.cip1559 = height >= self.transition_heights.cip1559;
222        spec.cip150 = height >= self.transition_heights.cip150;
223        spec.cip151 = height >= self.transition_heights.cip151;
224        spec.cip152 = height >= self.transition_heights.cip152;
225        spec.cip154 = height >= self.transition_heights.cip154;
226        spec.cip7702 = height >= self.transition_heights.cip7702;
227        let cip645 = height >= self.transition_heights.cip645;
228        spec.cip645 = CIP645Spec::new(cip645);
229        spec.eip2935 = height >= self.transition_heights.eip2935;
230        spec.eip7623 = height >= self.transition_heights.eip7623;
231        spec.cip_c2_fix = height >= self.transition_heights.cip_c2_fix;
232        spec.cancun_opcodes = number >= self.transition_numbers.cancun_opcodes;
233        spec.align_evm = height >= self.transition_heights.align_evm && cip645;
234        spec.eip7939 = height >= self.transition_heights.cip166;
235
236        spec.overwrite_gas_plan_by_cip();
237
238        spec
239    }
240
241    pub fn consensus_spec(&self, height: BlockHeight) -> ConsensusGasSpec {
242        let mut spec = ConsensusGasSpec::genesis_spec();
243        spec.cip1559 = height >= self.transition_heights.cip1559;
244        let cip645 = height >= self.transition_heights.cip645;
245        spec.cip645 = CIP645Spec::new(cip645);
246
247        spec.align_evm = height >= self.transition_heights.align_evm && cip645;
248
249        spec.overwrite_gas_plan_by_cip();
250
251        spec
252    }
253
254    #[cfg(test)]
255    pub fn spec_for_test(&self, number: u64) -> Spec {
256        self.spec(number, number)
257    }
258
259    /// Return the base reward for a block.
260    /// `past_block_count` may be used for reward decay again in the future.
261    pub fn base_reward_in_ucfx(
262        &self, _past_block_count: u64, height: BlockHeight,
263    ) -> U512 {
264        let (_, start_base_ward) = self.base_block_rewards.iter()
265            .rev()
266            .find(|&(block, _)| *block <= height)
267            .expect("Current block's reward is not found; this indicates a chain config error");
268        // Possible decay computation based on past_block_count.
269        U512::from(start_base_ward) * U512::from(ONE_UCFX_IN_DRIP)
270    }
271
272    pub fn custom_prefix(&self, height: BlockHeight) -> Option<Vec<Bytes>> {
273        if height >= self.transition_heights.cip40
274            && height < self.transition_heights.cip94h
275        {
276            Some(vec![TANZANITE_HEADER_CUSTOM_FIRST_ELEMENT.to_vec()])
277        } else if height >= self.transition_heights.cip94h
278            && height < self.transition_heights.cip112
279        {
280            Some(vec![DAO_VOTE_HEADER_CUSTOM_FIRST_ELEMENT.to_vec()])
281        } else if height >= self.transition_heights.cip112
282            && height < self.transition_heights.cip1559
283        {
284            Some(vec![CIP112_HEADER_CUSTOM_FIRST_ELEMENT.to_vec()])
285        } else if height >= self.transition_heights.cip1559 {
286            Some(vec![NEXT_HARDFORK_HEADER_CUSTOM_FIRST_ELEMENT.to_vec()])
287        } else {
288            None
289        }
290    }
291
292    pub fn can_pack_evm_transaction(&self, height: BlockHeight) -> bool {
293        height % self.evm_transaction_block_ratio == 0
294    }
295
296    pub fn chain_id(&self, epoch_height: u64, space: Space) -> u32 {
297        self.chain_id
298            .read()
299            .get_chain_id(epoch_height)
300            .in_space(space)
301    }
302
303    pub fn chain_id_map(&self, epoch_height: u64) -> BTreeMap<Space, u32> {
304        BTreeMap::from([
305            (Space::Native, self.chain_id(epoch_height, Space::Native)),
306            (
307                Space::Ethereum,
308                self.chain_id(epoch_height, Space::Ethereum),
309            ),
310        ])
311    }
312
313    pub fn init_base_price(&self) -> SpaceMap<U256> { self.min_base_price }
314
315    pub fn min_base_price(&self) -> SpaceMap<U256> { self.min_base_price }
316}