cfx_vm_types/
spec.rs

1// Copyright 2015-2018 Parity Technologies (UK) Ltd.
2// This file is part of Parity.
3
4// Parity is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Parity is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Parity.  If not, see <http://www.gnu.org/licenses/>.
16
17// Copyright 2019 Conflux Foundation. All rights reserved.
18// Conflux is free software and distributed under GNU General Public License.
19// See http://www.gnu.org/licenses/
20
21//! Cost spec and other parameterisations for the EVM.
22use cfx_types::{address_util::AddressUtil, Address};
23use primitives::{block::BlockHeight, BlockNumber};
24
25pub const CODE_PREFIX_7702: &'static [u8] = b"\xef\x01\x00";
26
27/// Definition of the cost spec and other parameterisations for the VM.
28#[derive(Debug, Clone)]
29pub struct Spec {
30    /// VM stack limit
31    pub stack_limit: usize,
32    /// Max number of nested calls/creates
33    pub max_depth: usize,
34    /// Gas prices for instructions in all tiers
35    pub tier_step_gas: [usize; 8],
36    /// Gas price for `EXP` opcode
37    pub exp_gas: usize,
38    /// Additional gas for `EXP` opcode for each byte of exponent
39    pub exp_byte_gas: usize,
40    /// Gas price for `SHA3` opcode
41    pub sha3_gas: usize,
42    /// Additional gas for `SHA3` opcode for each word of hashed memory
43    pub sha3_word_gas: usize,
44    /// Gas price for loading from storage. Code sload gas after CIP-645f:
45    /// EIP-2929
46    pub cold_sload_gas: usize,
47    /// Gas price for setting new value to storage (`storage==0`, `new!=0`)
48    pub sstore_set_gas: usize,
49    /// Gas price for altering value in storage
50    pub sstore_reset_gas: usize,
51    /// Gas refund for `SSTORE` clearing (when `storage!=0`, `new==0`)
52    pub sstore_refund_gas: usize,
53    /// Gas price for `JUMPDEST` opcode
54    pub jumpdest_gas: usize,
55    /// Gas price for `LOG*`
56    pub log_gas: usize,
57    /// Additional gas for data in `LOG*`
58    pub log_data_gas: usize,
59    /// Additional gas for each topic in `LOG*`
60    pub log_topic_gas: usize,
61    /// Gas price for `CREATE` opcode
62    pub create_gas: usize,
63    /// Gas price for `*CALL*` opcodes
64    pub call_gas: usize,
65    /// Stipend for transfer for `CALL|CALLCODE` opcode when `value>0`
66    pub call_stipend: usize,
67    /// Additional gas required for value transfer (`CALL|CALLCODE`)
68    pub call_value_transfer_gas: usize,
69    /// Additional gas for creating new account (`CALL|CALLCODE`)
70    pub call_new_account_gas: usize,
71    /// Refund for SUICIDE
72    pub suicide_refund_gas: usize,
73    /// Gas for used memory
74    pub memory_gas: usize,
75    /// Coefficient used to convert memory size to gas price for memory
76    pub quad_coeff_div: usize,
77    /// Cost for contract length when executing `CREATE`
78    pub create_data_gas: usize,
79    /// Maximum code size when creating a contract.
80    pub create_data_limit: usize,
81    /// Maximum init code size (CIP-645i: EIP-3860)
82    pub init_code_data_limit: usize,
83    /// Init code word size (CIP-645i: EIP-3860)
84    pub init_code_word_gas: usize,
85    /// Transaction cost
86    pub tx_gas: usize,
87    /// `CREATE` transaction cost
88    pub tx_create_gas: usize,
89    /// Additional cost for empty data transaction
90    pub tx_data_zero_gas: usize,
91    /// Aditional cost for non-empty data transaction
92    pub tx_data_non_zero_gas: usize,
93    /// Floor gas cost from empty data transaction (EIP-7623)
94    pub tx_data_floor_zero_gas: usize,
95    /// Floor gas cost from non-empty data transaction (EIP-7623)
96    pub tx_data_floor_non_zero_gas: usize,
97    /// Gas price for copying memory
98    pub copy_gas: usize,
99    /// Price of EXTCODESIZE
100    pub extcodesize_gas: usize,
101    /// Base price of EXTCODECOPY
102    pub extcodecopy_base_gas: usize,
103    /// Price of BALANCE
104    pub balance_gas: usize,
105    /// Price of EXTCODEHASH
106    pub extcodehash_gas: usize,
107    /// Price of SUICIDE
108    pub suicide_gas: usize,
109    /// Price for retiring PoS node.
110    pub retire_gas: usize,
111    /// Price for deploying Eip-1820 contract.
112    pub eip1820_gas: usize,
113    pub access_list_storage_key_gas: usize,
114    pub access_list_address_gas: usize,
115    pub cold_account_access_cost: usize,
116    pub warm_access_gas: usize,
117    /// Amount of additional gas to pay when SUICIDE credits a non-existant
118    /// account
119    pub suicide_to_new_account_cost: usize,
120    /// If Some(x):
121    ///     let limit = GAS * (x - 1) / x;
122    ///     let CALL's gas = min(requested, limit);
123    ///     let CREATE's gas = limit;
124    /// If None:
125    ///     let CALL's gas = (requested > GAS ? \[OOG\] : GAS);
126    ///     let CREATE's gas = GAS;
127    pub sub_gas_cap_divisor: Option<usize>,
128    /// Blockhash instruction gas cost.
129    pub blockhash_gas: usize,
130    /// The magnification of gas storage occupying related operaions.
131    pub evm_gas_ratio: usize,
132    /// `PER_AUTH_BASE_COST` in CIP-7702
133    pub per_auth_base_cost: usize,
134    /// `PER_EMPTY_ACCOUNT_COST` in CIP-7702
135    pub per_empty_account_cost: usize,
136    /// CIP-43: Introduce Finality via Voting Among Staked
137    pub cip43_init: bool,
138    pub cip43_contract: bool,
139    /// CIP-62: Enable EC-related builtin contract
140    pub cip62: bool,
141    /// CIP-64: Get current epoch number through internal contract
142    pub cip64: bool,
143    /// CIP-71: Disable anti-reentrancy
144    pub cip71: bool,
145    /// CIP-78: Correct `is_sponsored` fields in receipt
146    pub cip78a: bool,
147    /// CIP-78: Correct `is_sponsored` fields in receipt
148    pub cip78b: bool,
149    /// CIP-90: A Space that Fully EVM Compatible
150    pub cip90: bool,
151    /// CIP-94: On-chain Parameter DAO Vote
152    pub cip94: bool,
153    pub cip94_activation_block_number: u64,
154    pub params_dao_vote_period: u64,
155    /// CIP-97: Remove staking list
156    pub cip97: bool,
157    /// CIP-98: Fix espace bug
158    pub cip98: bool,
159    /// CIP-105: Minimal DAO votes requirement based on PoS votes.
160    pub cip105: bool,
161    pub cip_sigma_fix: bool,
162    /// CIP-107: Reduce storage collateral refund.
163    pub cip107: bool,
164    /// CIP-118: Query Unused Storage Points in Internal Contract
165    pub cip118: bool,
166    /// CIP-119: PUSH0 instruction
167    pub cip119: bool,
168    /// CIP-131: Retain Whitelist on Contract Deletion
169    pub cip131: bool,
170    /// CIP-132: Fix Static Context Check for Internal Contracts
171    pub cip132: bool,
172    /// CIP-133: Enhanced Block Hash Query
173    pub cip133_b: BlockNumber,
174    pub cip133_e: BlockHeight,
175    pub cip133_core: bool,
176    /// CIP-137: Base Fee Sharing in CIP-1559
177    pub cip137: bool,
178    /// CIP-1559: Fee Market Change for Conflux
179    pub cip1559: bool,
180    /// CIP-141: Disable Subroutine Opcodes
181    /// CIP-142: Transient Storage Opcodes
182    /// CIP-143: MCOPY (0x5e) Opcode for Efficient Memory Copy
183    pub cancun_opcodes: bool,
184    /// CIP-144: Point Evaluation Precompile from EIP-4844
185    pub cip144: bool,
186    /// CIP-145: Fix Receipts upon `NotEnoughBalance` Error
187    pub cip145: bool,
188    pub cip145_fix: bool,
189    /// CIP-150: Reject New Contract Code Starting with the 0xEF byte
190    pub cip150: bool,
191    /// CIP-151: SELFDESTRUCT only in Same Transaction
192    pub cip151: bool,
193    /// CIP-152: Reject Transactions from Senders with Deployed Code
194    pub cip152: bool,
195    /// CIP-154: Fix Inconsistent Implementation of TLOAD
196    pub cip154: bool,
197    /// CIP-7702: Set Code for EOA
198    pub cip7702: bool,
199    /// CIP-645: Align Conflux Gas Pricing with EVM
200    pub cip645: CIP645Spec,
201    /// EIP-2935: Serve historical block hashes from state
202    pub eip2935: bool,
203    /// EIP-7623: Increase calldata cost
204    pub eip7623: bool,
205    pub align_evm: bool,
206    pub cip_c2_fix: bool,
207    /// EIP-7939: Count Leading Zeros Instruction
208    pub eip7939: bool,
209}
210
211/// Represents the feature flags for CIP-645 implementation.
212///
213/// While the protocol treats these features as a single atomic upgrade,
214/// separating them into named fields is merely to make the code more
215/// maintainable and self-documenting.
216///
217/// IMPORTANT NOTE:
218/// All fields must be consistently set to either `true` (enabled) or `false`
219/// (disabled). Mixed states will lead to undefined behavior as these features
220/// were designed to be activated as a coordinated bundle in CIP-645.
221#[derive(Debug, Clone, Copy)]
222pub struct CIP645Spec {
223    /// EIP-1108: Reduces gas costs for alt_bn128 precompile  
224    pub eip1108: bool,
225
226    /// EIP-1884: Reprices trie-size-dependent opcodes  
227    pub eip1884: bool,
228
229    /// EIP-2028: Reduces Calldata gas cost  
230    pub eip2028: bool,
231
232    /// EIP-2200: Rebalances net-metered SSTORE gas cost  
233    /// EIP-3529: Removes gas refunds for SELFDESTRUCT and reduces SSTORE
234    /// refunds
235    pub eip_sstore_and_refund_gas: bool,
236
237    /// EIP-2565: Reduces gas cost for modular exponentiation transactions  
238    pub eip2565: bool,
239
240    /// EIP-2929: Increases gas costs for opcode transactions to mitigate DDoS
241    /// EIP-3651: Reduces gas fees for accessing COINBASE address  
242    pub eip_cold_warm_access: bool,
243
244    /// EIP-3860: Limits initcode size to 49152  
245    pub eip3860: bool,
246
247    /// EIP-684: Revert creation in case of collision
248    pub fix_eip684: bool,
249
250    /// EIP-1559: EIP-1559: Fee market change for ETH 1.0 chain
251    pub fix_eip1559: bool,
252
253    /// EIP-5656: MCOPY - Memory copying instruction
254    pub fix_eip5656: bool,
255
256    /// EIP-1153: Transient storage opcodes
257    pub fix_eip1153: bool,
258
259    pub blockhash_gas: bool,
260
261    pub opcode_update: bool,
262
263    pub fix_extcodehash: bool,
264}
265
266impl CIP645Spec {
267    pub const fn new(enabled: bool) -> Self {
268        Self {
269            eip1108: enabled,
270            eip1884: enabled,
271            eip2028: enabled,
272            eip_sstore_and_refund_gas: enabled,
273            eip2565: enabled,
274            eip_cold_warm_access: enabled,
275            eip3860: enabled,
276            fix_eip684: enabled,
277            fix_eip1153: enabled,
278            fix_eip1559: enabled,
279            fix_eip5656: enabled,
280            blockhash_gas: enabled,
281            opcode_update: enabled,
282            fix_extcodehash: enabled,
283        }
284    }
285}
286
287/// Spec parameters are determined solely by block height and thus accessible to
288/// the consensus protocol.
289#[derive(Debug, Clone)]
290pub struct ConsensusGasSpec {
291    /// EIP-7623: Increase calldata cost
292    pub eip7623: bool,
293    /// CIP-1559: Fee Market Change for Conflux
294    pub cip1559: bool,
295    /// CIP-645(GAS)
296    pub cip645: CIP645Spec,
297    /// Transaction cost
298    pub tx_gas: usize,
299    /// `CREATE` transaction cost
300    pub tx_create_gas: usize,
301    /// Additional cost for empty data transaction
302    pub tx_data_zero_gas: usize,
303    /// Aditional cost for non-empty data transaction
304    pub tx_data_non_zero_gas: usize,
305    /// Floor gas cost from empty data transaction (EIP-7623)
306    pub tx_data_floor_zero_gas: usize,
307    /// Floor gas cost from non-empty data transaction (EIP-7623)
308    pub tx_data_floor_non_zero_gas: usize,
309    /// Maximum init code size (CIP-645i: EIP-3860)
310    pub init_code_data_limit: usize,
311    /// Init code word size (CIP-645i: EIP-3860)
312    pub init_code_word_gas: usize,
313    pub access_list_storage_key_gas: usize,
314    pub access_list_address_gas: usize,
315    /// `PER_AUTH_BASE_COST` in CIP-7702
316    pub per_auth_base_cost: usize,
317    /// `PER_EMPTY_ACCOUNT_COST` in CIP-7702
318    pub per_empty_account_cost: usize,
319    /// The magnification of gas storage occupying related operaions.
320    pub evm_gas_ratio: usize,
321    pub align_evm: bool,
322}
323
324impl Spec {
325    /// The spec when Conflux launches the mainnet. It should never changed
326    /// since the mainnet has launched.
327    pub const fn genesis_spec() -> Spec {
328        Spec {
329            stack_limit: 1024,
330            max_depth: 1024,
331            tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
332            exp_gas: 10,
333            exp_byte_gas: 50,
334            sha3_gas: 30,
335            sha3_word_gas: 6,
336            // Become 800 after CIP-142
337            cold_sload_gas: 200,
338            sstore_set_gas: 20000,
339            sstore_reset_gas: 5000,
340            sstore_refund_gas: 15000,
341            jumpdest_gas: 1,
342            log_gas: 375,
343            log_data_gas: 8,
344            log_topic_gas: 375,
345            create_gas: 32000,
346            call_gas: 700,
347            call_stipend: 2300,
348            call_value_transfer_gas: 9000,
349            call_new_account_gas: 25000,
350            suicide_refund_gas: 24000,
351            memory_gas: 3,
352            quad_coeff_div: 512,
353            create_data_gas: 200,
354            create_data_limit: 49152,
355            init_code_data_limit: 49152,
356            init_code_word_gas: 2,
357            tx_gas: 21000,
358            tx_create_gas: 53000,
359            tx_data_zero_gas: 4,
360            tx_data_non_zero_gas: 68,
361            tx_data_floor_zero_gas: 10,
362            tx_data_floor_non_zero_gas: 40,
363            copy_gas: 3,
364            extcodesize_gas: 700,
365            extcodecopy_base_gas: 700,
366            extcodehash_gas: 400,
367            balance_gas: 400,
368            suicide_gas: 5000,
369            retire_gas: 5_000_000,
370            eip1820_gas: 1_500_000,
371            access_list_storage_key_gas: 1900,
372            access_list_address_gas: 2400,
373            cold_account_access_cost: 2600,
374            warm_access_gas: 100,
375            suicide_to_new_account_cost: 25000,
376            per_auth_base_cost: 17000,
377            per_empty_account_cost: 25000,
378            sub_gas_cap_divisor: Some(64),
379            blockhash_gas: 20,
380            cip43_init: false,
381            cip43_contract: false,
382            cip62: false,
383            cip64: false,
384            cip71: false,
385            cip90: false,
386            cip78a: false,
387            cip78b: false,
388            cip94: false,
389            evm_gas_ratio: 2,
390            cip94_activation_block_number: u64::MAX,
391            params_dao_vote_period: 0,
392            cip97: false,
393            cip98: false,
394            cip105: false,
395            cip_sigma_fix: false,
396            cip107: false,
397            cip118: false,
398            cip119: false,
399            cip131: false,
400            cip132: false,
401            cip133_b: u64::MAX,
402            cip133_e: u64::MAX,
403            cip133_core: false,
404            cip137: false,
405            cip145: false,
406            cip145_fix: false,
407            cip1559: false,
408            cancun_opcodes: false,
409            cip144: false,
410            cip150: false,
411            cip151: false,
412            cip152: false,
413            cip154: false,
414            cip645: CIP645Spec::new(false),
415            cip7702: false,
416            eip2935: false,
417            eip7623: false,
418            cip_c2_fix: false,
419            align_evm: false,
420            eip7939: false,
421        }
422    }
423
424    // `cold_sload_gas` replaces `sload_gas` in certain contexts, primarily for
425    // core space internal contracts. However, some `sload_gas` usages retain
426    // their original semantics. This function is introduced to distinguish
427    // these cases.
428    pub fn sload_gas(&self) -> usize {
429        assert!(!self.cip645.eip_cold_warm_access);
430        self.cold_sload_gas
431    }
432
433    pub fn overwrite_gas_plan_by_cip(&mut self) {
434        if self.cancun_opcodes {
435            self.cold_sload_gas = 800;
436        }
437        if self.cip645.eip1884 {
438            self.balance_gas = 700;
439            self.extcodehash_gas = 700;
440        }
441
442        if self.cip645.eip2028 {
443            self.tx_data_non_zero_gas = 16;
444        }
445
446        if self.cip645.eip_cold_warm_access {
447            self.cold_sload_gas = 2100;
448            self.sstore_reset_gas = 2900;
449        }
450
451        if self.align_evm {
452            self.per_auth_base_cost = 12500;
453            self.create_data_limit = 24576;
454            self.evm_gas_ratio = 1;
455        }
456
457        // Don't forget also update GenesisGasSpec::overwrite_gas_plan_by_cip
458    }
459
460    #[cfg(any(test, feature = "testonly_code"))]
461    pub fn new_spec_for_test() -> Spec { Self::genesis_spec() }
462
463    pub fn is_valid_address(&self, address: &Address) -> bool {
464        address.is_genesis_valid_address()
465    }
466
467    #[inline]
468    pub const fn to_consensus_spec(&self) -> ConsensusGasSpec {
469        ConsensusGasSpec {
470            cip1559: self.cip1559,
471            cip645: self.cip645,
472            eip7623: self.eip7623,
473            tx_gas: self.tx_gas,
474            tx_create_gas: self.tx_create_gas,
475            tx_data_zero_gas: self.tx_data_zero_gas,
476            tx_data_non_zero_gas: self.tx_data_non_zero_gas,
477            init_code_data_limit: self.init_code_data_limit,
478            init_code_word_gas: self.init_code_word_gas,
479            access_list_storage_key_gas: self.access_list_storage_key_gas,
480            access_list_address_gas: self.access_list_address_gas,
481            per_auth_base_cost: self.per_auth_base_cost,
482            per_empty_account_cost: self.per_empty_account_cost,
483            align_evm: self.align_evm,
484            evm_gas_ratio: self.evm_gas_ratio,
485            tx_data_floor_zero_gas: self.tx_data_floor_zero_gas,
486            tx_data_floor_non_zero_gas: self.tx_data_floor_non_zero_gas,
487        }
488    }
489}
490
491impl ConsensusGasSpec {
492    pub const fn genesis_spec() -> Self {
493        Spec::genesis_spec().to_consensus_spec()
494    }
495
496    pub fn overwrite_gas_plan_by_cip(&mut self) {
497        if self.cip645.eip2028 {
498            self.tx_data_non_zero_gas = 16;
499        }
500
501        if self.align_evm {
502            self.per_auth_base_cost = 12500;
503            self.evm_gas_ratio = 1;
504        }
505    }
506}
507
508#[cfg(any(test, feature = "testonly_code"))]
509impl Default for Spec {
510    fn default() -> Self { Spec::new_spec_for_test() }
511}
512
513pub fn extract_7702_payload(code: &[u8]) -> Option<Address> {
514    if code.starts_with(CODE_PREFIX_7702) {
515        let (_prefix, payload) = code.split_at(CODE_PREFIX_7702.len());
516        if payload.len() == Address::len_bytes() {
517            Some(Address::from_slice(payload))
518        } else {
519            None
520        }
521    } else {
522        None
523    }
524}