@@ -165,14 +165,13 @@ object PrecompiledContracts {
165
165
166
166
private val lengthBytes = 32
167
167
private val totalLengthBytes = 3 * lengthBytes
168
- private val GQUADDIVISOR = 20
169
168
170
169
def exec (inputData : ByteString ): Option [ByteString ] = {
171
170
val baseLength = getLength(inputData, 0 )
172
171
val expLength = getLength(inputData, 1 )
173
172
val modLength = getLength(inputData, 2 )
174
173
175
- val result =
174
+ val result = {
176
175
if (baseLength == 0 && modLength == 0 )
177
176
BigInt (0 )
178
177
else {
@@ -187,6 +186,7 @@ object PrecompiledContracts {
187
186
base.modPow(exp, mod)
188
187
}
189
188
}
189
+ }
190
190
Some (ByteString (ByteUtils .bigIntegerToBytes(result.bigInteger, modLength)))
191
191
}
192
192
@@ -201,58 +201,84 @@ object PrecompiledContracts {
201
201
safeAdd(safeAdd(totalLengthBytes, baseLength), expLength)
202
202
)
203
203
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
+ }
205
209
206
- val adjExpLen = adjExpLength(expBytes, expLength)
210
+ // Spec: https://eips.ethereum.org/EIPS/eip-198
211
+ object PostEIP198Cost {
212
+ private val GQUADDIVISOR = 20
207
213
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
+ }
210
219
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
215
226
else
216
- expBytes.take(lengthBytes).padToByteString(lengthBytes, 0 .toByte)
227
+ x2 / 16 + 480 * x - 199680
228
+ }
229
+ }
217
230
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
219
234
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
224
241
}
225
- }
226
242
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 )
230
246
}
231
247
232
248
private def getNumber (bytes : ByteString , offset : Int , length : Int ): BigInt = {
233
249
val number = bytes.slice(offset, safeAdd(offset, length)).padToByteString(length, 0 .toByte)
234
250
ByteUtils .toBigInt(number)
235
251
}
236
252
253
+ private def safeAdd (a : Int , b : Int ): Int = {
254
+ safeInt(BigInt (a) + BigInt (b))
255
+ }
256
+
237
257
private def safeInt (value : BigInt ): Int =
238
258
if (value.isValidInt)
239
259
value.toInt
240
260
else
241
261
Integer .MAX_VALUE
242
262
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)))
245
266
}
246
267
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)
249
274
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
+ }
256
282
}
257
283
}
258
284
0 commit comments