Skip to content

Commit 9915379

Browse files
authored
Route ModExp precompile in certain conditions (#8868)
Route ModExp precompile when base and modulus are even. This is to take advantage that Java and native are better in certain conditions, so they are routed appropriately to take advantage of each ones performance.
1 parent 1cb201f commit 9915379

File tree

2 files changed

+32
-12
lines changed

2 files changed

+32
-12
lines changed

app/src/main/java/org/hyperledger/besu/cli/options/NativeLibraryOptions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public class NativeLibraryOptions {
5353
"Per default a native library is used for modexp. "
5454
+ "If the Java implementation should be used instead, this option must be set to false",
5555
arity = "1")
56-
private final Boolean nativeModExp = Boolean.TRUE;
56+
private final Boolean nativeModExp = Boolean.FALSE;
5757

5858
/** Default constructor. */
5959
NativeLibraryOptions() {}

evm/src/main/java/org/hyperledger/besu/evm/precompile/BigIntegerModularExponentiationPrecompiledContract.java

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -116,22 +116,33 @@ public PrecompileContractResult computePrecompile(
116116
return PrecompileContractResult.halt(
117117
null, Optional.of(ExceptionalHaltReason.PRECOMPILE_ERROR));
118118
}
119+
120+
// OPTIMIZATION: overwrite native setting for this case
121+
if (LibArithmetic.ENABLED) {
122+
final int baseOffset = clampedToInt(BASE_OFFSET);
123+
final int baseLength = clampedToInt(length_of_BASE);
124+
final int modulusOffset = clampedToInt(BASE_OFFSET + length_of_BASE + length_of_EXPONENT);
125+
final int modulusLength = clampedToInt(length_of_MODULUS);
126+
if ((extractLastByte(input, baseOffset, baseLength) & 1) != 1
127+
&& (extractLastByte(input, modulusOffset, modulusLength) & 1) != 1) {
128+
return computeNative(input, modulusLength);
129+
}
130+
}
131+
119132
if (useNative) {
120-
return computeNative(input, length_of_MODULUS);
133+
final int modulusLength = clampedToInt(length_of_MODULUS);
134+
return computeNative(input, modulusLength);
121135
} else {
122-
return computeDefault(input, length_of_BASE, length_of_EXPONENT, length_of_MODULUS);
136+
final int baseLength = clampedToInt(length_of_BASE);
137+
final int exponentLength = clampedToInt(length_of_EXPONENT);
138+
final int modulusLength = clampedToInt(length_of_MODULUS);
139+
return computeDefault(input, baseLength, exponentLength, modulusLength);
123140
}
124141
}
125142

126143
@NotNull
127144
private PrecompileContractResult computeDefault(
128-
final Bytes input,
129-
final long length_of_BASE,
130-
final long length_of_EXPONENT,
131-
final long length_of_MODULUS) {
132-
final int baseLength = clampedToInt(length_of_BASE);
133-
final int exponentLength = clampedToInt(length_of_EXPONENT);
134-
final int modulusLength = clampedToInt(length_of_MODULUS);
145+
final Bytes input, final int baseLength, final int exponentLength, final int modulusLength) {
135146
// If baseLength and modulusLength are zero
136147
// we could have a massively overflowing exp because it wouldn't have been filtered out at the
137148
// gas cost phase
@@ -226,6 +237,16 @@ public static BigInteger extractParameter(final Bytes input, final int offset, f
226237
}
227238
}
228239

240+
private static byte extractLastByte(final Bytes input, final int offset, final int length) {
241+
if (offset >= input.size() || length == 0) {
242+
return 0;
243+
} else if (offset + length <= input.size()) {
244+
return input.get(offset + length - 1);
245+
}
246+
Bytes partial = input.slice(offset);
247+
return partial.get(partial.size() - 1);
248+
}
249+
229250
/**
230251
* Extract parameter.
231252
*
@@ -257,8 +278,7 @@ private static long square(final long n) {
257278
}
258279

259280
private PrecompileContractResult computeNative(
260-
final @NotNull Bytes input, final long length_of_MODULUS) {
261-
final int modulusLength = clampedToInt(length_of_MODULUS);
281+
final @NotNull Bytes input, final int modulusLength) {
262282
final IntByReference o_len = new IntByReference(modulusLength);
263283

264284
final byte[] result = new byte[modulusLength];

0 commit comments

Comments
 (0)