@@ -8,8 +8,6 @@ use primitive_types::U256;
88
99use crate :: PurePrecompile ;
1010
11- pub struct Modexp ;
12-
1311fn modexp ( base : & [ u8 ] , exponent : & [ u8 ] , modulus : & [ u8 ] ) -> Vec < u8 > {
1412 aurora_engine_modexp:: modexp ( base, exponent, modulus)
1513}
@@ -49,33 +47,13 @@ pub fn byzantium_gas_calc(base_len: u64, exp_len: u64, mod_len: u64, exp_highp:
4947
5048/// Calculate gas cost according to EIP 2565:
5149/// <https://eips.ethereum.org/EIPS/eip-2565>
52- #[ allow( unused) ]
5350fn berlin_gas_calc ( base_len : u64 , exp_len : u64 , mod_len : u64 , exp_highp : & U256 ) -> u64 {
5451 gas_calc :: < 200 , 8 , 3 , _ > ( base_len, exp_len, mod_len, exp_highp, |max_len| -> U256 {
5552 let words = U256 :: from ( max_len. div_ceil ( 8 ) ) ;
5653 words * words
5754 } )
5855}
5956
60- /// Calculate gas cost according to EIP-7883:
61- /// <https://eips.ethereum.org/EIPS/eip-7883>
62- ///
63- /// There are three changes:
64- /// 1. Increase minimal price from 200 to 500
65- /// 2. Increase cost when exponent is larger than 32 bytes
66- /// 3. Increase cost when base or modulus is larger than 32 bytes
67- #[ allow( unused) ]
68- fn osaka_gas_calc ( base_len : u64 , exp_len : u64 , mod_len : u64 , exp_highp : & U256 ) -> u64 {
69- gas_calc :: < 500 , 16 , 1 , _ > ( base_len, exp_len, mod_len, exp_highp, |max_len| -> U256 {
70- if max_len <= 32 {
71- return U256 :: from ( 16 ) ; // multiplication_complexity = 16
72- }
73-
74- let words = U256 :: from ( max_len. div_ceil ( 8 ) ) ;
75- words * words * U256 :: from ( 2 ) // multiplication_complexity = 2 * words**2
76- } )
77- }
78-
7957/// Calculate gas cost.
8058fn gas_calc < const MIN_PRICE : u64 , const MULTIPLIER : u64 , const GAS_DIVISOR : u64 , F > (
8159 base_len : u64 ,
@@ -162,63 +140,78 @@ pub fn left_pad_vec(data: &[u8], len: usize) -> Cow<'_, [u8]> {
162140 }
163141}
164142
165- impl < G : GasMutState > PurePrecompile < G > for Modexp {
166- fn execute ( & self , input : & [ u8 ] , gasometer : & mut G ) -> ( ExitResult , Vec < u8 > ) {
167- // The format of input is:
168- // <length_of_BASE> <length_of_EXPONENT> <length_of_MODULUS> <BASE> <EXPONENT> <MODULUS>
169- // Where every length is a 32-byte left-padded integer representing the number of bytes
170- // to be taken up by the next value.
171- const HEADER_LENGTH : usize = 96 ;
172-
173- // Extract the header
174- let base_len = U256 :: from_big_endian ( & right_pad_with_offset :: < 32 > ( input, 0 ) . into_owned ( ) ) ;
175- let exp_len = U256 :: from_big_endian ( & right_pad_with_offset :: < 32 > ( input, 32 ) . into_owned ( ) ) ;
176- let mod_len = U256 :: from_big_endian ( & right_pad_with_offset :: < 32 > ( input, 64 ) . into_owned ( ) ) ;
177-
178- // Cast base and modulus to usize, it does not make sense to handle larger values
179- let base_len = try_some ! ( usize :: try_from( base_len) . map_err( |_| ExitException :: OutOfGas ) ) ;
180- let mod_len = try_some ! ( usize :: try_from( mod_len) . map_err( |_| ExitException :: OutOfGas ) ) ;
181- // cast exp len to the max size, it will fail later in gas calculation if it is too large.
182- let exp_len = usize:: try_from ( exp_len) . unwrap_or ( usize:: MAX ) ;
183-
184- // TODO: Check Osaka size limit.
185-
186- // Used to extract ADJUSTED_EXPONENT_LENGTH.
187- let exp_highp_len = min ( exp_len, 32 ) ;
188-
189- // Throw away the header data as we already extracted lengths.
190- let input = input. get ( HEADER_LENGTH ..) . unwrap_or_default ( ) ;
191-
192- let exp_highp = {
193- // Get right padded bytes so if data.len is less then exp_len we will get right padded zeroes.
194- let right_padded_highp = right_pad_with_offset :: < 32 > ( input, base_len) ;
195- // If exp_len is less then 32 bytes get only exp_len bytes and do left padding.
196- let out = left_pad :: < 32 > ( & right_padded_highp[ ..exp_highp_len] ) ;
197- U256 :: from_big_endian ( & out. into_owned ( ) )
198- } ;
199-
200- // Check if we have enough gas.
201- let gas_cost =
202- byzantium_gas_calc ( base_len as u64 , exp_len as u64 , mod_len as u64 , & exp_highp) ;
203- try_some ! ( gasometer. record_gas( U256 :: from( gas_cost) ) ) ;
204-
205- if base_len == 0 && mod_len == 0 {
206- return ( ExitSucceed :: Returned . into ( ) , Vec :: new ( ) ) ;
207- }
143+ fn execute < G : GasMutState > (
144+ input : & [ u8 ] ,
145+ gasometer : & mut G ,
146+ gas_calc : fn ( u64 , u64 , u64 , & U256 ) -> u64 ,
147+ ) -> ( ExitResult , Vec < u8 > ) {
148+ // The format of input is:
149+ // <length_of_BASE> <length_of_EXPONENT> <length_of_MODULUS> <BASE> <EXPONENT> <MODULUS>
150+ // Where every length is a 32-byte left-padded integer representing the number of bytes
151+ // to be taken up by the next value.
152+ const HEADER_LENGTH : usize = 96 ;
153+
154+ // Extract the header
155+ let base_len = U256 :: from_big_endian ( & right_pad_with_offset :: < 32 > ( input, 0 ) . into_owned ( ) ) ;
156+ let exp_len = U256 :: from_big_endian ( & right_pad_with_offset :: < 32 > ( input, 32 ) . into_owned ( ) ) ;
157+ let mod_len = U256 :: from_big_endian ( & right_pad_with_offset :: < 32 > ( input, 64 ) . into_owned ( ) ) ;
158+
159+ // Cast base and modulus to usize, it does not make sense to handle larger values
160+ let base_len = try_some ! ( usize :: try_from( base_len) . map_err( |_| ExitException :: OutOfGas ) ) ;
161+ let mod_len = try_some ! ( usize :: try_from( mod_len) . map_err( |_| ExitException :: OutOfGas ) ) ;
162+ // cast exp len to the max size, it will fail later in gas calculation if it is too large.
163+ let exp_len = usize:: try_from ( exp_len) . unwrap_or ( usize:: MAX ) ;
164+
165+ // Used to extract ADJUSTED_EXPONENT_LENGTH.
166+ let exp_highp_len = min ( exp_len, 32 ) ;
167+
168+ // Throw away the header data as we already extracted lengths.
169+ let input = input. get ( HEADER_LENGTH ..) . unwrap_or_default ( ) ;
170+
171+ let exp_highp = {
172+ // Get right padded bytes so if data.len is less then exp_len we will get right padded zeroes.
173+ let right_padded_highp = right_pad_with_offset :: < 32 > ( input, base_len) ;
174+ // If exp_len is less then 32 bytes get only exp_len bytes and do left padding.
175+ let out = left_pad :: < 32 > ( & right_padded_highp[ ..exp_highp_len] ) ;
176+ U256 :: from_big_endian ( & out. into_owned ( ) )
177+ } ;
178+
179+ // Check if we have enough gas.
180+ let gas_cost = gas_calc ( base_len as u64 , exp_len as u64 , mod_len as u64 , & exp_highp) ;
181+ try_some ! ( gasometer. record_gas( U256 :: from( gas_cost) ) ) ;
182+
183+ if base_len == 0 && mod_len == 0 {
184+ return ( ExitSucceed :: Returned . into ( ) , Vec :: new ( ) ) ;
185+ }
186+
187+ // Padding is needed if the input does not contain all 3 values.
188+ let input_len = base_len. saturating_add ( exp_len) . saturating_add ( mod_len) ;
189+ let input = right_pad_vec ( input, input_len) ;
190+ let ( base, input) = input. split_at ( base_len) ;
191+ let ( exponent, modulus) = input. split_at ( exp_len) ;
192+ debug_assert_eq ! ( modulus. len( ) , mod_len) ;
193+
194+ // Call the modexp.
195+ let output = modexp ( base, exponent, modulus) ;
196+
197+ (
198+ ExitSucceed :: Returned . into ( ) ,
199+ left_pad_vec ( & output, mod_len) . into_owned ( ) ,
200+ )
201+ }
208202
209- // Padding is needed if the input does not contain all 3 values.
210- let input_len = base_len. saturating_add ( exp_len) . saturating_add ( mod_len) ;
211- let input = right_pad_vec ( input, input_len) ;
212- let ( base, input) = input. split_at ( base_len) ;
213- let ( exponent, modulus) = input. split_at ( exp_len) ;
214- debug_assert_eq ! ( modulus. len( ) , mod_len) ;
203+ pub struct ModexpByzantium ;
215204
216- // Call the modexp.
217- let output = modexp ( base, exponent, modulus) ;
205+ impl < G : GasMutState > PurePrecompile < G > for ModexpByzantium {
206+ fn execute ( & self , input : & [ u8 ] , gasometer : & mut G ) -> ( ExitResult , Vec < u8 > ) {
207+ execute ( input, gasometer, byzantium_gas_calc)
208+ }
209+ }
218210
219- (
220- ExitSucceed :: Returned . into ( ) ,
221- left_pad_vec ( & output, mod_len) . into_owned ( ) ,
222- )
211+ pub struct ModexpBerlin ;
212+
213+ impl < G : GasMutState > PurePrecompile < G > for ModexpBerlin {
214+ fn execute ( & self , input : & [ u8 ] , gasometer : & mut G ) -> ( ExitResult , Vec < u8 > ) {
215+ execute ( input, gasometer, berlin_gas_calc)
223216 }
224217}
0 commit comments