From 001cae9fa967ebc166e317ab207faaa15d259e35 Mon Sep 17 00:00:00 2001 From: Artem Vorotnikov Date: Mon, 8 Jun 2020 23:27:06 +0300 Subject: [PATCH 1/3] Use BigUint::modpow --- ethcore/builtin/src/lib.rs | 90 ++------------------------------------ 1 file changed, 3 insertions(+), 87 deletions(-) diff --git a/ethcore/builtin/src/lib.rs b/ethcore/builtin/src/lib.rs index 8ba36e963db..4bca18fe230 100644 --- a/ethcore/builtin/src/lib.rs +++ b/ethcore/builtin/src/lib.rs @@ -738,54 +738,6 @@ impl Implementation for Ripemd160 { } } -// calculate modexp: left-to-right binary exponentiation to keep multiplicands lower -fn modexp(mut base: BigUint, exp: Vec, modulus: BigUint) -> BigUint { - const BITS_PER_DIGIT: usize = 8; - - // n^m % 0 || n^m % 1 - if modulus <= BigUint::one() { - return BigUint::zero(); - } - - // normalize exponent - let mut exp = exp.into_iter().skip_while(|d| *d == 0).peekable(); - - // n^0 % m - if exp.peek().is_none() { - return BigUint::one(); - } - - // 0^n % m, n > 0 - if base.is_zero() { - return BigUint::zero(); - } - - base %= &modulus; - - // Fast path for base divisible by modulus. - if base.is_zero() { return BigUint::zero() } - - // Left-to-right binary exponentiation (Handbook of Applied Cryptography - Algorithm 14.79). - // http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf - let mut result = BigUint::one(); - - for digit in exp { - let mut mask = 1 << (BITS_PER_DIGIT - 1); - - for _ in 0..BITS_PER_DIGIT { - result = &result * &result % &modulus; - - if digit & mask > 0 { - result = result * &base % &modulus; - } - - mask >>= 1; - } - } - - result -} - impl Implementation for Modexp { fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { let mut reader = input.chain(io::repeat(0)); @@ -817,13 +769,10 @@ impl Implementation for Modexp { }; let base = read_num(&mut reader, base_len); - - let mut exp_buf = vec![0; exp_len]; - reader.read_exact(&mut exp_buf[..exp_len]).expect("reading from zero-extended memory cannot fail; qed"); - + let exponent = read_num(&mut reader, exp_len); let modulus = read_num(&mut reader, mod_len); - modexp(base, exp_buf, modulus) + base.modpow(&exponent, &modulus) }; // write output to given memory, left padded and same length as the modulus. @@ -1172,7 +1121,7 @@ mod tests { use parity_bytes::BytesRef; use super::{ Builtin, EthereumBuiltin, FromStr, Implementation, Linear, - ModexpPricer, modexp as me, Pricing, + ModexpPricer, Pricing, Bls12ConstOperations, Bls12PairingPrice,Bls12PairingPricer }; @@ -1296,39 +1245,6 @@ mod tests { assert_eq!(&out[..], &expected[..]); } - #[test] - fn modexp_func() { - // n^0 % m == 1 - let mut base = BigUint::parse_bytes(b"12345", 10).unwrap(); - let mut exp = BigUint::zero(); - let mut modulus = BigUint::parse_bytes(b"789", 10).unwrap(); - assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::one()); - - // 0^n % m == 0 - base = BigUint::zero(); - exp = BigUint::parse_bytes(b"12345", 10).unwrap(); - modulus = BigUint::parse_bytes(b"789", 10).unwrap(); - assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::zero()); - - // n^m % 1 == 0 - base = BigUint::parse_bytes(b"12345", 10).unwrap(); - exp = BigUint::parse_bytes(b"789", 10).unwrap(); - modulus = BigUint::one(); - assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::zero()); - - // if n % d == 0, then n^m % d == 0 - base = BigUint::parse_bytes(b"12345", 10).unwrap(); - exp = BigUint::parse_bytes(b"789", 10).unwrap(); - modulus = BigUint::parse_bytes(b"15", 10).unwrap(); - assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::zero()); - - // others - base = BigUint::parse_bytes(b"12345", 10).unwrap(); - exp = BigUint::parse_bytes(b"789", 10).unwrap(); - modulus = BigUint::parse_bytes(b"97", 10).unwrap(); - assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::parse_bytes(b"55", 10).unwrap()); - } - #[test] fn identity() { let f = EthereumBuiltin::from_str("identity").unwrap(); From e6f6ca50d2f329b915e2ebcd0bcf777c3b0b65e0 Mon Sep 17 00:00:00 2001 From: Artem Vorotnikov Date: Tue, 9 Jun 2020 00:42:22 +0300 Subject: [PATCH 2/3] Fixes --- ethcore/builtin/src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ethcore/builtin/src/lib.rs b/ethcore/builtin/src/lib.rs index 4bca18fe230..b6bf5364d2e 100644 --- a/ethcore/builtin/src/lib.rs +++ b/ethcore/builtin/src/lib.rs @@ -772,7 +772,11 @@ impl Implementation for Modexp { let exponent = read_num(&mut reader, exp_len); let modulus = read_num(&mut reader, mod_len); - base.modpow(&exponent, &modulus) + if modulus.is_zero() || modulus.is_one() { + BigUint::zero() + } else { + base.modpow(&exponent, &modulus) + } }; // write output to given memory, left padded and same length as the modulus. From 08b2171ad9a206805964fef58d2d52a0a418ef92 Mon Sep 17 00:00:00 2001 From: Artem Vorotnikov Date: Fri, 12 Jun 2020 17:01:14 +0300 Subject: [PATCH 3/3] Fix unused import --- ethcore/builtin/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/ethcore/builtin/src/lib.rs b/ethcore/builtin/src/lib.rs index b6bf5364d2e..b7a332ba63b 100644 --- a/ethcore/builtin/src/lib.rs +++ b/ethcore/builtin/src/lib.rs @@ -1121,7 +1121,6 @@ mod tests { }; use hex_literal::hex; use maplit::btreemap; - use num::{BigUint, Zero, One}; use parity_bytes::BytesRef; use super::{ Builtin, EthereumBuiltin, FromStr, Implementation, Linear,