@@ -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-
789741impl 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