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    /// A parameter for temporary safety guard for hn_fix
67    pub max_difficulty_guard: Option<U256>,
68    /// A parameter for temporary safety guard for hn_fix
69    pub max_finalize_confirmation_guard: Option<u64>,
70}
71
72#[derive(Default, Debug, Clone)]
73pub struct TransitionsBlockNumber {
74    /// CIP-43: Introduce Finality Through Staking Vote
75    pub cip43a: BlockNumber,
76    pub cip43b: BlockNumber,
77    /// CIP-62: Enable EC-Related Builtin Contracts
78    pub cip62: BlockNumber,
79    /// CIP-64: Get Current Epoch Number via Internal Contract
80    pub cip64: BlockNumber,
81    /// CIP-71: Disable Anti-Reentrancy
82    pub cip71: BlockNumber,
83    /// CIP-78: Correct `is_sponsored` Fields in Receipt
84    pub cip78a: BlockNumber,
85    pub cip78b: BlockNumber,
86    /// CIP-90: Introduce a Fully EVM-Compatible Space
87    pub cip90b: BlockNumber,
88    /// CIP-92: Enable Blake2F Builtin Function
89    pub cip92: BlockNumber,
90    /// CIP-94: On-Chain DAO Vote for Chain Parameters
91    pub cip94n: BlockNumber,
92    /// CIP-97: Clear Staking Lists
93    pub cip97: BlockNumber,
94    /// CIP-98: Fix BLOCKHASH Opcode Bug in eSpace
95    pub cip98: BlockNumber,
96    /// CIP-105: Minimal DAO Vote Count Based on PoS Staking
97    pub cip105: BlockNumber,
98    /// CIP-107: DAO-Adjustable Burn of Storage Collateral
99    pub cip107: BlockNumber,
100    /// A security fix without a publicly submitted CIP
101    pub cip_sigma_fix: BlockNumber,
102    /// CIP-118: Query Unused Storage Points in Internal Contract
103    pub cip118: BlockNumber,
104    /// CIP-119: PUSH0 instruction
105    pub cip119: BlockNumber,
106    /// CIP-131: Retain Whitelist on Contract Deletion
107    pub cip131: BlockNumber,
108    /// CIP-132: Fix Static Context Check for Internal Contracts
109    pub cip132: BlockNumber,
110    /// CIP-133: Enhanced Block Hash Query
111    pub cip133b: BlockNumber,
112    /// CIP-137: Base Fee Sharing in CIP-1559
113    pub cip137: BlockNumber,
114    /// CIP-141: Disable Subroutine Opcodes
115    /// CIP-142: Transient Storage Opcodes
116    /// CIP-143: MCOPY (0x5e) Opcode for Efficient Memory Copy
117    pub cancun_opcodes: BlockNumber,
118    /// CIP-144: Point Evaluation Precompile from EIP-4844
119    pub cip144: BlockNumber,
120    /// CIP-145: Fix Receipts upon `NotEnoughBalance` Error
121    pub cip145: BlockNumber,
122}
123
124#[derive(Default, Debug, Clone)]
125pub struct TransitionsEpochHeight {
126    /// CIP-40: Reduce Block Base Reward to 2 CFX
127    pub cip40: BlockHeight,
128    /// CIP-76: Remove VM-Related Constraints in Syncing Blocks
129    pub cip76: BlockHeight,
130    /// CIP-86: Update Difficulty Adjustment Algorithm
131    pub cip86: BlockHeight,
132    /// CIP-90: Introduce a Fully EVM-Compatible Space
133    pub cip90a: BlockHeight,
134    /// CIP-94: On-Chain DAO Vote for Chain Parameters
135    pub cip94h: BlockHeight,
136    /// CIP-112: Fix Block Headers `custom` Field Serde
137    pub cip112: BlockHeight,
138    /// CIP-130: Aligning Gas Limit with Transaction Size
139    pub cip130: BlockHeight,
140    /// CIP-133: Enhanced Block Hash Query
141    pub cip133e: BlockHeight,
142    /// CIP-1559: Fee Market Change for Conflux
143    pub cip1559: BlockHeight,
144    /// CIP-150: Reject New Contract Code Starting with the 0xEF byte
145    pub cip150: BlockHeight,
146    /// CIP-151: SELFDESTRUCT only in Same Transaction
147    pub cip151: BlockHeight,
148    /// CIP-152: Reject Transactions from Senders with Deployed Code
149    pub cip152: BlockHeight,
150    /// CIP-154: Fix Inconsistent Implementation of TLOAD
151    pub cip154: BlockHeight,
152    /// CIP-7702: Set Code for EOA
153    pub cip7702: BlockHeight,
154    /// CIP-645: Align Conflux Gas Pricing with EVM
155    pub cip645: BlockHeight,
156    pub align_evm: BlockHeight,
157    /// EIP-2935: Serve historical block hashes from state
158    pub eip2935: BlockHeight,
159    /// EIP-2537: Precompile for BLS12-381 curve operations
160    pub eip2537: BlockHeight,
161    /// EIP-7623: Increase calldata cost
162    pub eip7623: BlockHeight,
163    pub cip_c2_fix: BlockHeight,
164    pub cip145_fix: BlockHeight,
165    /// EIP-7939: Count Leading Zeros Instruction
166    pub cip166: BlockHeight,
167    /// EIP-7212 / RIP-7212: precompile secp256r1 activation height
168    pub cip167: BlockHeight,
169    /// CIP-172: Canonical Transaction RLP Encoding. Height at/after which a
170    /// block with a non-canonically-encoded tx is invalid.
171    pub cip172: BlockHeight,
172    /// CIP-174: EIP-7823 (ModExp input upper bounds) and EIP-7883 (ModExp
173    /// gas cost increase)
174    pub cip174: BlockHeight,
175    /// CIP-175: Resolve EIP-7702 Delegation in Cross-Space Calls
176    pub cip175: BlockHeight,
177    /// CIP-176: Merge Storage Keys of Repeated Addresses in an Access List
178    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    /// Return the base reward for a block.
282    /// `past_block_count` may be used for reward decay again in the future.
283    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        // Possible decay computation based on past_block_count.
291        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}