From 48caef749741a1be1d69b58d67313306cbc1b49b Mon Sep 17 00:00:00 2001 From: Artem Vorotnikov Date: Thu, 21 May 2020 22:54:07 +0300 Subject: [PATCH] Implement EIP-2565 (option B) --- ethcore/builtin/src/lib.rs | 19 ++++++++++++++++--- ethcore/res/ethereum/foundation.json | 10 +++++++--- json/src/spec/builtin.rs | 15 +++++++++++++-- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/ethcore/builtin/src/lib.rs b/ethcore/builtin/src/lib.rs index 8f9dde5fc3e..5bbdc356a87 100644 --- a/ethcore/builtin/src/lib.rs +++ b/ethcore/builtin/src/lib.rs @@ -30,6 +30,7 @@ use std::{ use byteorder::{BigEndian, LittleEndian, ReadBytesExt}; use common_types::errors::EthcoreError; use ethereum_types::{H256, U256}; +use ethjson::spec::builtin::ModexpMultComplexity; use parity_crypto::publickey::{recover_allowing_all_zero_message, Signature, ZeroesAllowedMessage}; use keccak_hash::keccak; use log::{warn, trace}; @@ -102,6 +103,7 @@ struct Linear { #[derive(Debug)] struct ModexpPricer { divisor: u64, + mult_complexity_formula: ModexpMultComplexity, } impl Pricer for Linear { @@ -180,7 +182,12 @@ impl Pricer for ModexpPricer { let adjusted_exp_len = Self::adjusted_exp_len(exp_len, exp_low); - let (gas, overflow) = Self::mult_complexity(m).overflowing_mul(max(adjusted_exp_len, 1)); + let complexity_formula = match self.mult_complexity_formula { + ModexpMultComplexity::Eip198 => Self::mult_complexity, + ModexpMultComplexity::Eip2565 => Self::mult_complexity_new, + }; + + let (gas, overflow) = (complexity_formula)(m).overflowing_mul(max(adjusted_exp_len, 1)); if overflow { return U256::max_value(); } @@ -205,6 +212,10 @@ impl ModexpPricer { x => (x * x) / 16 + 480 * x - 199_680, } } + + fn mult_complexity_new(x: u64) -> u64 { + ((x / 64) + if x % 64 == 0 { 0 } else { 1 }) ^ 2 + } } /// Pricing scheme, execution definition, and activation block for a built-in contract. @@ -281,7 +292,8 @@ impl From for Pricing { 10 } else { exp.divisor - } + }, + mult_complexity_formula: exp.mult_complexity_formula, }) } ethjson::spec::builtin::Pricing::AltBn128Pairing(pricer) => { @@ -758,6 +770,7 @@ impl Bn128Pairing { #[cfg(test)] mod tests { + use super::*; use std::convert::TryFrom; use ethereum_types::U256; use ethjson::spec::builtin::{ @@ -1037,7 +1050,7 @@ mod tests { #[test] fn modexp() { let f = Builtin { - pricer: btreemap![0 => Pricing::Modexp(ModexpPricer { divisor: 20 })], + pricer: btreemap![0 => Pricing::Modexp(ModexpPricer { divisor: 20, mult_complexity_formula: ModexpMultComplexity::Eip198 })], native: EthereumBuiltin::from_str("modexp").unwrap(), }; diff --git a/ethcore/res/ethereum/foundation.json b/ethcore/res/ethereum/foundation.json index 1949efb0093..9477a669328 100644 --- a/ethcore/res/ethereum/foundation.json +++ b/ethcore/res/ethereum/foundation.json @@ -4827,10 +4827,14 @@ "0x0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", - "activate_at": "0x42ae50", "pricing": { - "modexp": { - "divisor": 20 + "0x42ae50": { + "price": { + "modexp": { + "divisor": 20, + "mult_complexity_formula": "eip198" + } + } } } } diff --git a/json/src/spec/builtin.rs b/json/src/spec/builtin.rs index 173975fafe7..e4d7d0f10ba 100644 --- a/json/src/spec/builtin.rs +++ b/json/src/spec/builtin.rs @@ -30,6 +30,15 @@ pub struct Linear { /// Price for word. pub word: u64, } +/// Computational complexity for modular exponentiation. +#[derive(Debug, PartialEq, Deserialize, Clone)] +#[serde(rename_all = "lowercase", deny_unknown_fields)] +pub enum ModexpMultComplexity { + /// Computational complexity formula as defined in EIP-198 + Eip198, + /// Computational complexity formula as defined in EIP-2565 + Eip2565, +} /// Pricing for modular exponentiation. #[derive(Debug, PartialEq, Deserialize, Clone)] @@ -37,6 +46,8 @@ pub struct Linear { pub struct Modexp { /// Price divisor. pub divisor: u64, + /// Computational complexity function + pub mult_complexity_formula: ModexpMultComplexity, } /// Pricing for constant alt_bn128 operations (ECADD and ECMUL) @@ -139,7 +150,7 @@ pub struct PricingAt { #[cfg(test)] mod tests { - use super::{Builtin, BuiltinCompat, Pricing, PricingAt, Linear, Modexp, AltBn128ConstOperations}; + use super::*; use maplit::btreemap; #[test] @@ -238,7 +249,7 @@ mod tests { assert_eq!(builtin.pricing, btreemap![ 100_000 => PricingAt { info: None, - price: Pricing::Modexp(Modexp { divisor: 5 }) + price: Pricing::Modexp(Modexp { divisor: 5, mult_complexity_formula: ModexpMultComplexity::Eip198 }) } ]); }