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