From d8a0d382292a0afb9986dcfbea9e022f617bb5f1 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Mon, 13 Jan 2020 22:54:00 +0100 Subject: [PATCH] Fix Aztlan hard fork issues (#11347) * Fix Aztlan hard fork issues * Fix mordor block number * Fix classic block number * Add missing precompiles * Make EIP-1283's comments reflact the current spec Co-authored-by: Niklas Adolfsson --- ethcore/evm/src/interpreter/gasometer.rs | 66 +++++++++++++++--------- ethcore/res/ethereum/classic.json | 25 +++++++-- ethcore/res/ethereum/kotti.json | 1 + ethcore/res/ethereum/mordor.json | 3 +- ethcore/types/src/engines/params.rs | 9 ++++ ethcore/vm/src/schedule.rs | 4 ++ json/src/spec/params.rs | 2 + 7 files changed, 81 insertions(+), 29 deletions(-) diff --git a/ethcore/evm/src/interpreter/gasometer.rs b/ethcore/evm/src/interpreter/gasometer.rs index 1930ebf03..478bee04a 100644 --- a/ethcore/evm/src/interpreter/gasometer.rs +++ b/ethcore/evm/src/interpreter/gasometer.rs @@ -375,32 +375,40 @@ fn to_word_size(value: Gas) -> (Gas, bool) { fn calculate_eip1283_sstore_gas(schedule: &Schedule, original: &U256, current: &U256, new: &U256) -> Gas { Gas::from( if current == new { - // 1. If current value equals new value (this is a no-op), 200 gas is deducted. - schedule.sload_gas + // 1. If current value equals new value (this is a no-op), `SSTORE_DIRTY_GAS` + // (or if not set, `SLOAD_GAS`) is deducted. + schedule.sstore_dirty_gas.unwrap_or(schedule.sload_gas) } else { // 2. If current value does not equal new value if original == current { - // 2.1. If original value equals current value (this storage slot has not been changed by the current execution context) + // 2.1. If original value equals current value (this storage slot has not + // been changed by the current execution context) if original.is_zero() { - // 2.1.1. If original value is 0, 20000 gas is deducted. + // 2.1.1. If original value is 0, `SSTORE_SET_GAS` is deducted. schedule.sstore_set_gas } else { - // 2.1.2. Otherwise, 5000 gas is deducted. + // 2.1.2. Otherwise, `SSTORE_RESET_GAS` gas is deducted. schedule.sstore_reset_gas - // 2.1.2.1. If new value is 0, add 15000 gas to refund counter. + // 2.1.2.1. If new value is 0, add `SSTORE_CLEARS_SCHEDULE` to refund counter. } } else { - // 2.2. If original value does not equal current value (this storage slot is dirty), 200 gas is deducted. Apply both of the following clauses. - schedule.sload_gas + // 2.2. If original value does not equal current value (this storage slot is + // dirty), `SSTORE_DIRTY_GAS` (or if not set, `SLOAD_GAS`) is deducted. + // Apply both of the following clauses. + schedule.sstore_dirty_gas.unwrap_or(schedule.sload_gas) // 2.2.1. If original value is not 0 - // 2.2.1.1. If current value is 0 (also means that new value is not 0), remove 15000 gas from refund counter. We can prove that refund counter will never go below 0. - // 2.2.1.2. If new value is 0 (also means that current value is not 0), add 15000 gas to refund counter. + // 2.2.1.1. If current value is 0 (also means that new value is not 0), remove + // `SSTORE_SET_GAS - SSTORE_DIRTY_GAS` from refund counter. + // 2.2.1.2. If new value is 0 (also means that current value is not 0), add + // `SSTORE_CLEARS_SCHEDULE` to refund counter. // 2.2.2. If original value equals new value (this storage slot is reset) - // 2.2.2.1. If original value is 0, add 19800 gas to refund counter. - // 2.2.2.2. Otherwise, add 4800 gas to refund counter. + // 2.2.2.1. If original value is 0, add `SSTORE_SET_GAS - SSTORE_DIRTY_GAS` + // to refund counter. + // 2.2.2.2. Otherwise, add `SSTORE_RESET_GAS - SSTORE_DIRTY_GAS` + // to refund counter. } } ) @@ -410,30 +418,36 @@ pub fn handle_eip1283_sstore_clears_refund(ext: &mut dyn vm::Ext, original: &U25 let sstore_clears_schedule = ext.schedule().sstore_refund_gas; if current == new { - // 1. If current value equals new value (this is a no-op), 200 gas is deducted. + // 1. If current value equals new value (this is a no-op), `SSTORE_DIRTY_GAS` + // (or if not set, `SLOAD_GAS`) is deducted. } else { // 2. If current value does not equal new value if original == current { - // 2.1. If original value equals current value (this storage slot has not been changed by the current execution context) + // 2.1. If original value equals current value (this storage slot has not + // been changed by the current execution context) if original.is_zero() { - // 2.1.1. If original value is 0, 20000 gas is deducted. + // 2.1.1. If original value is 0, `SSTORE_SET_GAS` is deducted. } else { - // 2.1.2. Otherwise, 5000 gas is deducted. + // 2.1.2. Otherwise, `SSTORE_RESET_GAS` gas is deducted. if new.is_zero() { - // 2.1.2.1. If new value is 0, add 15000 gas to refund counter. + // 2.1.2.1. If new value is 0, add `SSTORE_CLEARS_SCHEDULE` to refund counter. ext.add_sstore_refund(sstore_clears_schedule); } } } else { - // 2.2. If original value does not equal current value (this storage slot is dirty), 200 gas is deducted. Apply both of the following clauses. + // 2.2. If original value does not equal current value (this storage slot is + // dirty), `SSTORE_DIRTY_GAS` (or if not set, `SLOAD_GAS`) is deducted. + // Apply both of the following clauses. if !original.is_zero() { // 2.2.1. If original value is not 0 if current.is_zero() { - // 2.2.1.1. If current value is 0 (also means that new value is not 0), remove 15000 gas from refund counter. We can prove that refund counter will never go below 0. + // 2.2.1.1. If current value is 0 (also means that new value is not 0), remove + // `SSTORE_SET_GAS - SSTORE_DIRTY_GAS` from refund counter. ext.sub_sstore_refund(sstore_clears_schedule); } else if new.is_zero() { - // 2.2.1.2. If new value is 0 (also means that current value is not 0), add 15000 gas to refund counter. + // 2.2.1.2. If new value is 0 (also means that current value is not 0), add + // `SSTORE_CLEARS_SCHEDULE` to refund counter. ext.add_sstore_refund(sstore_clears_schedule); } } @@ -441,12 +455,16 @@ pub fn handle_eip1283_sstore_clears_refund(ext: &mut dyn vm::Ext, original: &U25 if original == new { // 2.2.2. If original value equals new value (this storage slot is reset) if original.is_zero() { - // 2.2.2.1. If original value is 0, add 19800 gas to refund counter. - let refund = ext.schedule().sstore_set_gas - ext.schedule().sload_gas; + // 2.2.2.1. If original value is 0, add `SSTORE_SET_GAS - SSTORE_DIRTY_GAS` + // to refund counter. + let refund = ext.schedule().sstore_set_gas + - ext.schedule().sstore_dirty_gas.unwrap_or(ext.schedule().sload_gas); ext.add_sstore_refund(refund); } else { - // 2.2.2.2. Otherwise, add 4800 gas to refund counter. - let refund = ext.schedule().sstore_reset_gas - ext.schedule().sload_gas; + // 2.2.2.2. Otherwise, add `SSTORE_RESET_GAS - SSTORE_DIRTY_GAS` + // to refund counter. + let refund = ext.schedule().sstore_reset_gas + - ext.schedule().sstore_dirty_gas.unwrap_or(ext.schedule().sload_gas); ext.add_sstore_refund(refund); } } diff --git a/ethcore/res/ethereum/classic.json b/ethcore/res/ethereum/classic.json index 85de09aa0..5571e2c2a 100644 --- a/ethcore/res/ethereum/classic.json +++ b/ethcore/res/ethereum/classic.json @@ -40,7 +40,12 @@ "eip658Transition": "0x85d9a0", "eip145Transition": "0x921288", "eip1014Transition": "0x921288", - "eip1052Transition": "0x921288" + "eip1052Transition": "0x921288", + "eip1283Transition": "0xa03ae7", + "eip1344Transition": "0xa03ae7", + "eip1706Transition": "0xa03ae7", + "eip2028Transition": "0xa03ae7", + "eip2200AdvanceTransition": "0xa03ae7" }, "genesis": { "seal": { @@ -4425,7 +4430,7 @@ "0x85d9a0": { "price": { "alt_bn128_const_operations": { "price": 500 }} }, - "0x7fffffffffffff": { + "0xa03ae7": { "price": { "alt_bn128_const_operations": { "price": 150 }} } } @@ -4438,7 +4443,7 @@ "0x85d9a0": { "price": { "alt_bn128_const_operations": { "price": 40000 }} }, - "0x7fffffffffffff": { + "0xa03ae7": { "price": { "alt_bn128_const_operations": { "price": 6000 }} } } @@ -4451,12 +4456,24 @@ "0x85d9a0": { "price": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 }} }, - "0x7fffffffffffff": { + "0xa03ae7": { "price": { "alt_bn128_pairing": { "base": 45000, "pair": 34000 }} } } } }, + "0x0000000000000000000000000000000000000009": { + "balance": "0x1", + "builtin": { + "name": "blake2_f", + "activate_at": "0x1f67cf", + "pricing": { + "blake2_f": { + "gas_per_round": 1 + } + } + } + }, "3282791d6fd713f1e94f4bfd565eaa78b3a0599d": { "balance": "1337000000000000000000" }, diff --git a/ethcore/res/ethereum/kotti.json b/ethcore/res/ethereum/kotti.json index 25ba61961..52019bcdc 100644 --- a/ethcore/res/ethereum/kotti.json +++ b/ethcore/res/ethereum/kotti.json @@ -28,6 +28,7 @@ "eip1344Transition": "0x1f67cf", "eip1706Transition": "0x1f67cf", "eip2028Transition": "0x1f67cf", + "eip2200AdvanceTransition": "0x1f67cf", "gasLimitBoundDivisor": "0x400", "maxCodeSize": "0x6000", "maxCodeSizeTransition": "0xaef49", diff --git a/ethcore/res/ethereum/mordor.json b/ethcore/res/ethereum/mordor.json index c5ae911f0..1ea7d2bde 100644 --- a/ethcore/res/ethereum/mordor.json +++ b/ethcore/res/ethereum/mordor.json @@ -41,7 +41,8 @@ "eip1283Transition":"0xbe10b", "eip1344Transition":"0xbe10b", "eip1706Transition":"0xbe10b", - "eip2028Transition":"0xbe10b" + "eip2028Transition":"0xbe10b", + "eip2200AdvanceTransition": "0xbe10b" }, "genesis":{ "seal":{ diff --git a/ethcore/types/src/engines/params.rs b/ethcore/types/src/engines/params.rs index be44bb213..fe05a1714 100644 --- a/ethcore/types/src/engines/params.rs +++ b/ethcore/types/src/engines/params.rs @@ -100,6 +100,8 @@ pub struct CommonParams { pub eip1884_transition: BlockNumber, /// Number of first block where EIP-2028 rules begin. pub eip2028_transition: BlockNumber, + /// Number of first block where EIP-2200 advance transition begin. + pub eip2200_advance_transition: BlockNumber, /// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin. pub dust_protection_transition: BlockNumber, /// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled. @@ -185,6 +187,9 @@ impl CommonParams { if block_number >= self.eip2028_transition { schedule.tx_data_non_zero_gas = 16; } + if block_number >= self.eip2200_advance_transition { + schedule.sstore_dirty_gas = Some(800); + } if block_number >= self.eip210_transition { schedule.blockhash_gas = 800; } @@ -322,6 +327,10 @@ impl From for CommonParams { BlockNumber::max_value, Into::into, ), + eip2200_advance_transition: p.eip2200_advance_transition.map_or_else( + BlockNumber::max_value, + Into::into, + ), dust_protection_transition: p.dust_protection_transition.map_or_else( BlockNumber::max_value, Into::into, diff --git a/ethcore/vm/src/schedule.rs b/ethcore/vm/src/schedule.rs index f3b7afbf1..89b67d156 100644 --- a/ethcore/vm/src/schedule.rs +++ b/ethcore/vm/src/schedule.rs @@ -53,6 +53,8 @@ pub struct Schedule { pub sha3_word_gas: usize, /// Gas price for loading from storage pub sload_gas: usize, + /// Special gas price for dirty gas of SSTORE, after net gas metering. + pub sstore_dirty_gas: Option, /// Gas price for setting new value to storage (`storage==0`, `new!=0`) pub sstore_set_gas: usize, /// Gas price for altering value in storage @@ -240,6 +242,7 @@ impl Schedule { sha3_gas: 30, sha3_word_gas: 6, sload_gas: 200, + sstore_dirty_gas: None, sstore_set_gas: 20000, sstore_reset_gas: 5000, sstore_refund_gas: 15000, @@ -331,6 +334,7 @@ impl Schedule { sha3_gas: 30, sha3_word_gas: 6, sload_gas: 50, + sstore_dirty_gas: None, sstore_set_gas: 20000, sstore_reset_gas: 5000, sstore_refund_gas: 15000, diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index f29076549..b858ef766 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -107,6 +107,8 @@ pub struct Params { /// See `CommonParams` docs. pub eip2028_transition: Option, /// See `CommonParams` docs. + pub eip2200_advance_transition: Option, + /// See `CommonParams` docs. pub dust_protection_transition: Option, /// See `CommonParams` docs. pub nonce_cap_increment: Option,