Skip to content
This repository was archived by the owner on Nov 6, 2020. It is now read-only.

Commit 1165549

Browse files
authored
Use BigUint::modpow for ModExp precompile (#11772)
1 parent 5d5352a commit 1165549

File tree

1 file changed

+7
-88
lines changed

1 file changed

+7
-88
lines changed

ethcore/builtin/src/lib.rs

Lines changed: 7 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -738,54 +738,6 @@ impl Implementation for Ripemd160 {
738738
}
739739
}
740740

741-
// calculate modexp: left-to-right binary exponentiation to keep multiplicands lower
742-
fn modexp(mut base: BigUint, exp: Vec<u8>, modulus: BigUint) -> BigUint {
743-
const BITS_PER_DIGIT: usize = 8;
744-
745-
// n^m % 0 || n^m % 1
746-
if modulus <= BigUint::one() {
747-
return BigUint::zero();
748-
}
749-
750-
// normalize exponent
751-
let mut exp = exp.into_iter().skip_while(|d| *d == 0).peekable();
752-
753-
// n^0 % m
754-
if exp.peek().is_none() {
755-
return BigUint::one();
756-
}
757-
758-
// 0^n % m, n > 0
759-
if base.is_zero() {
760-
return BigUint::zero();
761-
}
762-
763-
base %= &modulus;
764-
765-
// Fast path for base divisible by modulus.
766-
if base.is_zero() { return BigUint::zero() }
767-
768-
// Left-to-right binary exponentiation (Handbook of Applied Cryptography - Algorithm 14.79).
769-
// http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
770-
let mut result = BigUint::one();
771-
772-
for digit in exp {
773-
let mut mask = 1 << (BITS_PER_DIGIT - 1);
774-
775-
for _ in 0..BITS_PER_DIGIT {
776-
result = &result * &result % &modulus;
777-
778-
if digit & mask > 0 {
779-
result = result * &base % &modulus;
780-
}
781-
782-
mask >>= 1;
783-
}
784-
}
785-
786-
result
787-
}
788-
789741
impl Implementation for Modexp {
790742
fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> {
791743
let mut reader = input.chain(io::repeat(0));
@@ -817,13 +769,14 @@ impl Implementation for Modexp {
817769
};
818770

819771
let base = read_num(&mut reader, base_len);
820-
821-
let mut exp_buf = vec![0; exp_len];
822-
reader.read_exact(&mut exp_buf[..exp_len]).expect("reading from zero-extended memory cannot fail; qed");
823-
772+
let exponent = read_num(&mut reader, exp_len);
824773
let modulus = read_num(&mut reader, mod_len);
825774

826-
modexp(base, exp_buf, modulus)
775+
if modulus.is_zero() || modulus.is_one() {
776+
BigUint::zero()
777+
} else {
778+
base.modpow(&exponent, &modulus)
779+
}
827780
};
828781

829782
// write output to given memory, left padded and same length as the modulus.
@@ -1168,11 +1121,10 @@ mod tests {
11681121
};
11691122
use hex_literal::hex;
11701123
use maplit::btreemap;
1171-
use num::{BigUint, Zero, One};
11721124
use parity_bytes::BytesRef;
11731125
use super::{
11741126
Builtin, EthereumBuiltin, FromStr, Implementation, Linear,
1175-
ModexpPricer, modexp as me, Pricing,
1127+
ModexpPricer, Pricing,
11761128
Bls12ConstOperations,
11771129
Bls12PairingPrice,Bls12PairingPricer
11781130
};
@@ -1296,39 +1248,6 @@ mod tests {
12961248
assert_eq!(&out[..], &expected[..]);
12971249
}
12981250

1299-
#[test]
1300-
fn modexp_func() {
1301-
// n^0 % m == 1
1302-
let mut base = BigUint::parse_bytes(b"12345", 10).unwrap();
1303-
let mut exp = BigUint::zero();
1304-
let mut modulus = BigUint::parse_bytes(b"789", 10).unwrap();
1305-
assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::one());
1306-
1307-
// 0^n % m == 0
1308-
base = BigUint::zero();
1309-
exp = BigUint::parse_bytes(b"12345", 10).unwrap();
1310-
modulus = BigUint::parse_bytes(b"789", 10).unwrap();
1311-
assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::zero());
1312-
1313-
// n^m % 1 == 0
1314-
base = BigUint::parse_bytes(b"12345", 10).unwrap();
1315-
exp = BigUint::parse_bytes(b"789", 10).unwrap();
1316-
modulus = BigUint::one();
1317-
assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::zero());
1318-
1319-
// if n % d == 0, then n^m % d == 0
1320-
base = BigUint::parse_bytes(b"12345", 10).unwrap();
1321-
exp = BigUint::parse_bytes(b"789", 10).unwrap();
1322-
modulus = BigUint::parse_bytes(b"15", 10).unwrap();
1323-
assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::zero());
1324-
1325-
// others
1326-
base = BigUint::parse_bytes(b"12345", 10).unwrap();
1327-
exp = BigUint::parse_bytes(b"789", 10).unwrap();
1328-
modulus = BigUint::parse_bytes(b"97", 10).unwrap();
1329-
assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::parse_bytes(b"55", 10).unwrap());
1330-
}
1331-
13321251
#[test]
13331252
fn identity() {
13341253
let f = EthereumBuiltin::from_str("identity").unwrap();

0 commit comments

Comments
 (0)