diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index 029f87b005ba..68188b4c6cbe 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -139,6 +139,7 @@ import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.ImmutableDiffBasedSubStorageConfiguration; import org.hyperledger.besu.evm.precompile.AbstractAltBnPrecompiledContract; +import org.hyperledger.besu.evm.precompile.AbstractPrecompiledContract; import org.hyperledger.besu.evm.precompile.BigIntegerModularExponentiationPrecompiledContract; import org.hyperledger.besu.evm.precompile.KZGPointEvalPrecompiledContract; import org.hyperledger.besu.metrics.BesuMetricCategory; @@ -696,6 +697,11 @@ static class PrivacyOptionGroup { description = "Specifies the number of last blocks to cache (default: ${DEFAULT-VALUE})") private final Integer numberOfblocksToCache = 0; + @CommandLine.Option( + names = {"--cache-precompiles"}, + description = "Specifies whether to cache precompile results (default: ${DEFAULT-VALUE})") + private final Boolean enablePrecompileCaching = true; + // Plugins Configuration Option Group @CommandLine.ArgGroup(validate = false) PluginsConfigurationOptions pluginsConfigurationOptions = new PluginsConfigurationOptions(); @@ -971,6 +977,7 @@ public void run() { VersionMetadata.versionCompatibilityChecks(versionCompatibilityProtection, dataDir()); configureNativeLibs(); + AbstractPrecompiledContract.setPrecompileCaching(enablePrecompileCaching); besuController = buildController(); besuPluginContext.beforeExternalServices(); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/precompile/AbstractPrecompiledContract.java b/evm/src/main/java/org/hyperledger/besu/evm/precompile/AbstractPrecompiledContract.java index b09c1b91042e..025cee874b84 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/precompile/AbstractPrecompiledContract.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/precompile/AbstractPrecompiledContract.java @@ -53,4 +53,10 @@ protected GasCalculator gasCalculator() { public String getName() { return name; } + + protected static Boolean enableResultCaching = Boolean.TRUE; + + public static void setPrecompileCaching(final boolean enablePrecompileCaching) { + enableResultCaching = enablePrecompileCaching; + } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/precompile/AltBN128AddPrecompiledContract.java b/evm/src/main/java/org/hyperledger/besu/evm/precompile/AltBN128AddPrecompiledContract.java index 1d0389f0a680..fc43860236e9 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/precompile/AltBN128AddPrecompiledContract.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/precompile/AltBN128AddPrecompiledContract.java @@ -37,7 +37,6 @@ public class AltBN128AddPrecompiledContract extends AbstractAltBnPrecompiledCont private static final int PARAMETER_LENGTH = 128; private final long gasCost; - private static final Cache bnAddCache = Caffeine.newBuilder().maximumSize(1000).build(); @@ -79,19 +78,24 @@ public long gasRequirement(final Bytes input) { @Override public PrecompileContractResult computePrecompile( final Bytes input, @Nonnull final MessageFrame messageFrame) { - var cachedRes = bnAddCache.getIfPresent(input.hashCode()); - if (cachedRes != null && cachedRes.cachedInput().equals(input)) { - return cachedRes.cachedResult(); - } - PrecompileInputResultTuple calculatedRes; + PrecompileInputResultTuple res; + + if (enableResultCaching) { + res = bnAddCache.getIfPresent(input.hashCode()); + if (res != null && res.cachedInput().equals(input)) { + return res.cachedResult(); + } + } if (useNative) { - calculatedRes = new PrecompileInputResultTuple(input, computeNative(input, messageFrame)); + res = new PrecompileInputResultTuple(input, computeNative(input, messageFrame)); } else { - calculatedRes = new PrecompileInputResultTuple(input, computeDefault(input)); + res = new PrecompileInputResultTuple(input, computeDefault(input)); + } + if (enableResultCaching) { + bnAddCache.put(input.hashCode(), res); } - bnAddCache.put(input.hashCode(), calculatedRes); - return calculatedRes.cachedResult(); + return res.cachedResult(); } private static PrecompileContractResult computeDefault(final Bytes input) { diff --git a/evm/src/main/java/org/hyperledger/besu/evm/precompile/AltBN128MulPrecompiledContract.java b/evm/src/main/java/org/hyperledger/besu/evm/precompile/AltBN128MulPrecompiledContract.java index 35c293b11a8e..cbbd8daebdde 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/precompile/AltBN128MulPrecompiledContract.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/precompile/AltBN128MulPrecompiledContract.java @@ -84,9 +84,12 @@ public long gasRequirement(final Bytes input) { public PrecompileContractResult computePrecompile( final Bytes input, @Nonnull final MessageFrame messageFrame) { - var res = bnMulCache.getIfPresent(input.hashCode()); - if (res != null && res.cachedInput().equals(input)) { - return res.cachedResult(); + PrecompileInputResultTuple res; + if (enableResultCaching) { + res = bnMulCache.getIfPresent(input.hashCode()); + if (res != null && res.cachedInput().equals(input)) { + return res.cachedResult(); + } } if (input.size() >= 64 && input.slice(0, 64).equals(POINT_AT_INFINITY)) { @@ -99,7 +102,9 @@ public PrecompileContractResult computePrecompile( } else { res = new PrecompileInputResultTuple(input, computeDefault(input)); } - bnMulCache.put(input.hashCode(), res); + if (enableResultCaching) { + bnMulCache.put(input.hashCode(), res); + } return res.cachedResult(); } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/precompile/AltBN128PairingPrecompiledContract.java b/evm/src/main/java/org/hyperledger/besu/evm/precompile/AltBN128PairingPrecompiledContract.java index 9d1406c24d3e..7baa5951ec27 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/precompile/AltBN128PairingPrecompiledContract.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/precompile/AltBN128PairingPrecompiledContract.java @@ -42,7 +42,10 @@ public class AltBN128PairingPrecompiledContract extends AbstractAltBnPrecompiled private static final int FIELD_LENGTH = 32; private static final int PARAMETER_LENGTH = 192; private static final Cache bnPairingCache = - Caffeine.newBuilder().maximumWeight(16_000_000).weigher((k, v) -> ((Bytes) k).size()).build(); + Caffeine.newBuilder() + .maximumWeight(16_000_000) + .weigher((k, v) -> ((PrecompileInputResultTuple) v).cachedInput().size()) + .build(); /** The constant FALSE. */ static final Bytes FALSE = @@ -103,16 +106,22 @@ public PrecompileContractResult computePrecompile( return PrecompileContractResult.halt( null, Optional.of(ExceptionalHaltReason.PRECOMPILE_ERROR)); } - var res = bnPairingCache.getIfPresent(input.hashCode()); - if (res != null && res.cachedInput().equals(input)) { - return res.cachedResult(); + PrecompileInputResultTuple res; + if (enableResultCaching) { + res = bnPairingCache.getIfPresent(input.hashCode()); + if (res != null && res.cachedInput().equals(input)) { + return res.cachedResult(); + } } if (useNative) { res = new PrecompileInputResultTuple(input, computeNative(input, messageFrame)); } else { res = new PrecompileInputResultTuple(input, computeDefault(input)); } - bnPairingCache.put(input.hashCode(), res); + if (enableResultCaching) { + bnPairingCache.put(input.hashCode(), res); + } + return res.cachedResult(); } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/precompile/BLAKE2BFPrecompileContract.java b/evm/src/main/java/org/hyperledger/besu/evm/precompile/BLAKE2BFPrecompileContract.java index 1c5c4da4c67c..bfa0847059f9 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/precompile/BLAKE2BFPrecompileContract.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/precompile/BLAKE2BFPrecompileContract.java @@ -81,14 +81,22 @@ public PrecompileContractResult computePrecompile( return PrecompileContractResult.halt( null, Optional.of(ExceptionalHaltReason.PRECOMPILE_ERROR)); } - var res = blakeCache.getIfPresent(input.hashCode()); - if (res != null && res.cachedInput().equals(input)) { - return res.cachedResult(); + PrecompileInputResultTuple res = null; + if (enableResultCaching) { + res = blakeCache.getIfPresent(input.hashCode()); + if (res != null && res.cachedInput().equals(input)) { + return res.cachedResult(); + } } + res = new PrecompileInputResultTuple( input, PrecompileContractResult.success(Hash.blake2bf(input))); - blakeCache.put(input.hashCode(), res); + + if (enableResultCaching) { + blakeCache.put(input.hashCode(), res); + } + return res.cachedResult(); } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/precompile/ECRECPrecompiledContract.java b/evm/src/main/java/org/hyperledger/besu/evm/precompile/ECRECPrecompiledContract.java index 588dab3c3d24..fb5c2ce23fee 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/precompile/ECRECPrecompiledContract.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/precompile/ECRECPrecompiledContract.java @@ -82,9 +82,13 @@ public PrecompileContractResult computePrecompile( return PrecompileContractResult.success(Bytes.EMPTY); } - var res = ecrecCache.getIfPresent(input.hashCode()); - if (res != null && res.cachedInput().equals(input)) { - return res.cachedResult(); + PrecompileInputResultTuple res; + + if (enableResultCaching) { + res = ecrecCache.getIfPresent(input.hashCode()); + if (res != null && res.cachedInput().equals(input)) { + return res.cachedResult(); + } } final int recId = d.get(63) - V_BASE; @@ -115,7 +119,9 @@ public PrecompileContractResult computePrecompile( final MutableBytes32 result = MutableBytes32.create(); hashed.slice(12).copyTo(result, 12); res = new PrecompileInputResultTuple(input, PrecompileContractResult.success(result)); - ecrecCache.put(input.hashCode(), res); + if (enableResultCaching) { + ecrecCache.put(input.hashCode(), res); + } return res.cachedResult(); } catch (final IllegalArgumentException e) { return PrecompileContractResult.success(Bytes.EMPTY);