@@ -165,14 +165,13 @@ object PrecompiledContracts {
165165
166166 private val lengthBytes = 32
167167 private val totalLengthBytes = 3 * lengthBytes
168- private val GQUADDIVISOR = 20
169168
170169 def exec (inputData : ByteString ): Option [ByteString ] = {
171170 val baseLength = getLength(inputData, 0 )
172171 val expLength = getLength(inputData, 1 )
173172 val modLength = getLength(inputData, 2 )
174173
175- val result =
174+ val result = {
176175 if (baseLength == 0 && modLength == 0 )
177176 BigInt (0 )
178177 else {
@@ -187,6 +186,7 @@ object PrecompiledContracts {
187186 base.modPow(exp, mod)
188187 }
189188 }
189+ }
190190 Some (ByteString (ByteUtils .bigIntegerToBytes(result.bigInteger, modLength)))
191191 }
192192
@@ -201,58 +201,84 @@ object PrecompiledContracts {
201201 safeAdd(safeAdd(totalLengthBytes, baseLength), expLength)
202202 )
203203
204- val multComplexity = getMultComplexity(math.max(baseLength, modLength))
204+ if (ethFork >= EthForks .Berlin || etcFork >= EtcForks .Magneto )
205+ PostEIP2565Cost .calculate(baseLength, modLength, expLength, expBytes)
206+ else
207+ PostEIP198Cost .calculate(baseLength, modLength, expLength, expBytes)
208+ }
205209
206- val adjExpLen = adjExpLength(expBytes, expLength)
210+ // Spec: https://eips.ethereum.org/EIPS/eip-198
211+ object PostEIP198Cost {
212+ private val GQUADDIVISOR = 20
207213
208- multComplexity * math.max(adjExpLen, 1 ) / GQUADDIVISOR
209- }
214+ def calculate (baseLength : Int , modLength : Int , expLength : Int , expBytes : ByteString ): BigInt = {
215+ val multComplexity = getMultComplexity(math.max(baseLength, modLength))
216+ val adjusted = adjustExpLength(expBytes, expLength)
217+ multComplexity * math.max(adjusted, 1 ) / GQUADDIVISOR
218+ }
210219
211- private def adjExpLength (expBytes : ByteString , expLength : Int ): Long = {
212- val expHead =
213- if (expLength <= lengthBytes)
214- expBytes.padToByteString(expLength, 0 .toByte)
220+ private def getMultComplexity (x : BigInt ): BigInt = {
221+ val x2 = x * x
222+ if (x <= 64 )
223+ x2
224+ else if (x <= 1024 )
225+ x2 / 4 + 96 * x - 3072
215226 else
216- expBytes.take(lengthBytes).padToByteString(lengthBytes, 0 .toByte)
227+ x2 / 16 + 480 * x - 199680
228+ }
229+ }
217230
218- val highestBitIndex = math.max(ByteUtils .toBigInt(expHead).bitLength - 1 , 0 )
231+ // Spec: https://eips.ethereum.org/EIPS/eip-2565
232+ object PostEIP2565Cost {
233+ private val GQUADDIVISOR = 3
219234
220- if (expLength <= lengthBytes) {
221- highestBitIndex
222- } else {
223- 8L * (expLength - lengthBytes) + highestBitIndex
235+ def calculate (baseLength : Int , modLength : Int , expLength : Int , expBytes : ByteString ): BigInt = {
236+ val multComplexity = getMultComplexity(math.max(baseLength, modLength))
237+ val adjusted = adjustExpLength(expBytes, expLength)
238+ val r = multComplexity * math.max(adjusted, 1 ) / GQUADDIVISOR
239+ if (r <= 200 ) 200
240+ else r
224241 }
225- }
226242
227- private def getLength ( bytes : ByteString , position : Int ) : Int = {
228- val start = position * lengthBytes
229- safeInt( ByteUtils .toBigInt(bytes.slice(start, start + lengthBytes)) )
243+ // ceiling(x/8)^2
244+ private def getMultComplexity ( x : BigInt ) : BigInt =
245+ ((x + 7 ) / 8 ).pow( 2 )
230246 }
231247
232248 private def getNumber (bytes : ByteString , offset : Int , length : Int ): BigInt = {
233249 val number = bytes.slice(offset, safeAdd(offset, length)).padToByteString(length, 0 .toByte)
234250 ByteUtils .toBigInt(number)
235251 }
236252
253+ private def safeAdd (a : Int , b : Int ): Int = {
254+ safeInt(BigInt (a) + BigInt (b))
255+ }
256+
237257 private def safeInt (value : BigInt ): Int =
238258 if (value.isValidInt)
239259 value.toInt
240260 else
241261 Integer .MAX_VALUE
242262
243- private def safeAdd (a : Int , b : Int ): Int = {
244- safeInt(BigInt (a) + BigInt (b))
263+ private def getLength (bytes : ByteString , position : Int ): Int = {
264+ val start = position * lengthBytes
265+ safeInt(ByteUtils .toBigInt(bytes.slice(start, start + lengthBytes)))
245266 }
246267
247- private def getMultComplexity (x : BigInt ): BigInt = {
248- val x2 = x * x
268+ private def adjustExpLength (expBytes : ByteString , expLength : Int ): Long = {
269+ val expHead =
270+ if (expLength <= lengthBytes)
271+ expBytes.padToByteString(expLength, 0 .toByte)
272+ else
273+ expBytes.take(lengthBytes).padToByteString(lengthBytes, 0 .toByte)
249274
250- if (x <= 64 )
251- x2
252- else if (x <= 1024 )
253- x2 / 4 + 96 * x - 3072
254- else
255- x2 / 16 + 480 * x - 199680
275+ val highestBitIndex = math.max(ByteUtils .toBigInt(expHead).bitLength - 1 , 0 )
276+
277+ if (expLength <= lengthBytes) {
278+ highestBitIndex
279+ } else {
280+ 8L * (expLength - lengthBytes) + highestBitIndex
281+ }
256282 }
257283 }
258284
0 commit comments