From a514614f2dc16310175e4727a3d9ed740c47961f Mon Sep 17 00:00:00 2001 From: "Danno Ferrin (shemnon)" Date: Fri, 10 Nov 2023 12:41:14 -0700 Subject: [PATCH] Opcode Tracing --- .../MainnetBesuControllerBuilder.java | 6 +- .../flat/RewardTraceGeneratorTest.java | 12 ++- .../mainnet/AbstractBlockProcessor.java | 10 +- .../besu/ethereum/mainnet/BlockProcessor.java | 55 ---------- .../mainnet/ClassicBlockProcessor.java | 7 +- .../mainnet/ClassicProtocolSpecs.java | 6 +- .../mainnet/MainnetBlockProcessor.java | 7 +- .../mainnet/MainnetProtocolSchedule.java | 34 +++++- .../mainnet/MainnetProtocolSpecs.java | 11 +- .../mainnet/MetricsOperationTracer.java | 100 ++++++++++++++++++ .../mainnet/ProtocolScheduleBuilder.java | 77 +++++--------- .../ethereum/mainnet/ProtocolSpecBuilder.java | 28 +++-- .../BlockImportExceptionHandlingTest.java | 3 +- .../mainnet/AbstractBlockProcessorTest.java | 4 +- .../mainnet/MainnetBlockProcessorTest.java | 7 +- .../NoRewardProtocolScheduleWrapper.java | 4 +- .../besu/metrics/BesuMetricCategory.java | 3 +- 17 files changed, 233 insertions(+), 141 deletions(-) create mode 100644 ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MetricsOperationTracer.java diff --git a/besu/src/main/java/org/hyperledger/besu/controller/MainnetBesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/MainnetBesuControllerBuilder.java index 8942f337e3b..f968dd90587 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/MainnetBesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/MainnetBesuControllerBuilder.java @@ -91,7 +91,11 @@ protected PluginServiceFactory createAdditionalPluginServices( @Override protected ProtocolSchedule createProtocolSchedule() { return MainnetProtocolSchedule.fromConfig( - configOptionsSupplier.get(), privacyParameters, isRevertReasonEnabled, evmConfiguration); + configOptionsSupplier.get(), + privacyParameters, + isRevertReasonEnabled, + evmConfiguration, + metricsSystem); } @Override diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/flat/RewardTraceGeneratorTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/flat/RewardTraceGeneratorTest.java index f8275182051..67d1d04d4bd 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/flat/RewardTraceGeneratorTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/flat/RewardTraceGeneratorTest.java @@ -32,11 +32,11 @@ import org.hyperledger.besu.ethereum.mainnet.MiningBeneficiaryCalculator; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; +import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import java.util.Collections; import java.util.List; import java.util.OptionalLong; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.tuweni.bytes.Bytes; @@ -91,7 +91,8 @@ public void assertThatTraceGeneratorReturnValidRewardsForMainnetBlockProcessor() blockReward, BlockHeader::getCoinbase, true, - protocolSchedule); + protocolSchedule, + new NoOpMetricsSystem()); when(protocolSpec.getBlockProcessor()).thenReturn(blockProcessor); final Stream traceStream = @@ -131,7 +132,7 @@ public void assertThatTraceGeneratorReturnValidRewardsForMainnetBlockProcessor() .type("reward") .build(); - final List traces = traceStream.collect(Collectors.toList()); + final List traces = traceStream.toList(); // check block reward assertThat(traces.get(0)).usingRecursiveComparison().isEqualTo(blocReward); @@ -151,7 +152,8 @@ public void assertThatTraceGeneratorReturnValidRewardsForClassicBlockProcessor() BlockHeader::getCoinbase, true, eraRounds, - protocolSchedule); + protocolSchedule, + new NoOpMetricsSystem()); when(protocolSpec.getBlockProcessor()).thenReturn(blockProcessor); final Stream traceStream = @@ -191,7 +193,7 @@ public void assertThatTraceGeneratorReturnValidRewardsForClassicBlockProcessor() .type("reward") .build(); - final List traces = traceStream.collect(Collectors.toList()); + final List traces = traceStream.toList(); // check block reward assertThat(traces.get(0)).usingRecursiveComparison().isEqualTo(blocReward); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java index 103fb3782d1..f1c4d058afe 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java @@ -35,9 +35,9 @@ import org.hyperledger.besu.ethereum.trie.MerkleTrieException; import org.hyperledger.besu.ethereum.vm.BlockHashLookup; import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; -import org.hyperledger.besu.evm.tracing.OperationTracer; import org.hyperledger.besu.evm.worldstate.WorldState; import org.hyperledger.besu.evm.worldstate.WorldUpdater; +import org.hyperledger.besu.plugin.services.MetricsSystem; import java.text.MessageFormat; import java.util.ArrayList; @@ -74,19 +74,23 @@ TransactionReceipt create( protected final MiningBeneficiaryCalculator miningBeneficiaryCalculator; + protected final MetricsOperationTracer metricsTracer; + protected AbstractBlockProcessor( final MainnetTransactionProcessor transactionProcessor, final TransactionReceiptFactory transactionReceiptFactory, final Wei blockReward, final MiningBeneficiaryCalculator miningBeneficiaryCalculator, final boolean skipZeroBlockRewards, - final ProtocolSchedule protocolSchedule) { + final ProtocolSchedule protocolSchedule, + final MetricsSystem metricsSystem) { this.transactionProcessor = transactionProcessor; this.transactionReceiptFactory = transactionReceiptFactory; this.blockReward = blockReward; this.miningBeneficiaryCalculator = miningBeneficiaryCalculator; this.skipZeroBlockRewards = skipZeroBlockRewards; this.protocolSchedule = protocolSchedule; + metricsTracer = new MetricsOperationTracer(metricsSystem); } @Override @@ -141,7 +145,7 @@ public BlockProcessingResult processBlock( blockHeader, transaction, miningBeneficiary, - OperationTracer.NO_TRACING, + metricsTracer, blockHashLookup, true, TransactionValidationParams.processingBlock(), diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BlockProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BlockProcessor.java index 060bce5bd77..d7f9e9b6452 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BlockProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BlockProcessor.java @@ -22,7 +22,6 @@ import org.hyperledger.besu.ethereum.core.Deposit; import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.Transaction; -import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.core.Withdrawal; import org.hyperledger.besu.ethereum.privacy.storage.PrivateMetadataUpdater; @@ -32,40 +31,6 @@ /** Processes a block. */ public interface BlockProcessor { - /** A block processing result. */ - interface Result { - - /** - * The receipts generated for the transactions in a block - * - *

This is only valid when {@code BlockProcessor#isSuccessful} returns {@code true}. - * - * @return the receipts generated for the transactions in a block - */ - List getReceipts(); - - /** - * The private receipts generated for the private transactions in a block when in - * goQuorumCompatibilityMode - * - *

This is only valid when {@code BlockProcessor#isSuccessful} returns {@code true}. - * - * @return the receipts generated for the private transactions in a block - */ - List getPrivateReceipts(); - - /** - * Returns whether the block was successfully processed. - * - * @return {@code true} if the block was processed successfully; otherwise {@code false} - */ - boolean isSuccessful(); - - default boolean isFailed() { - return !isSuccessful(); - } - } - /** * Processes the block. * @@ -137,26 +102,6 @@ BlockProcessingResult processBlock( Optional> deposits, PrivateMetadataUpdater privateMetadataUpdater); - /** - * Processes the block when running Besu in GoQuorum-compatible mode - * - * @param blockchain the blockchain to append the block to - * @param worldState the world state to apply public transactions to - * @param privateWorldState the private world state to apply private transaction to - * @param block the block to process - * @return the block processing result - */ - default BlockProcessingResult processBlock( - final Blockchain blockchain, - final MutableWorldState worldState, - final MutableWorldState privateWorldState, - final Block block) { - /* - This method should never be executed. All GoQuorum processing must happen in the GoQuorumBlockProcessor. - */ - throw new IllegalStateException("Tried to process GoQuorum block on AbstractBlockProcessor"); - } - /** * Get ommer reward in ${@link Wei} * diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicBlockProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicBlockProcessor.java index 044017b8728..fdc44bce700 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicBlockProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicBlockProcessor.java @@ -19,6 +19,7 @@ import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.evm.account.MutableAccount; import org.hyperledger.besu.evm.worldstate.WorldUpdater; +import org.hyperledger.besu.plugin.services.MetricsSystem; import java.math.BigInteger; import java.util.List; @@ -42,14 +43,16 @@ public ClassicBlockProcessor( final MiningBeneficiaryCalculator miningBeneficiaryCalculator, final boolean skipZeroBlockRewards, final OptionalLong eraLen, - final ProtocolSchedule protocolSchedule) { + final ProtocolSchedule protocolSchedule, + final MetricsSystem metricsSystem) { super( transactionProcessor, transactionReceiptFactory, blockReward, miningBeneficiaryCalculator, skipZeroBlockRewards, - protocolSchedule); + protocolSchedule, + metricsSystem); eraLength = eraLen.orElse(DEFAULT_ERA_LENGTH); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicProtocolSpecs.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicProtocolSpecs.java index 5d193168b31..0cb7d31d275 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicProtocolSpecs.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicProtocolSpecs.java @@ -107,7 +107,8 @@ public static ProtocolSpecBuilder gothamDefinition( blockReward, miningBeneficiaryCalculator, skipZeroBlockRewards, - protocolSchedule) -> + protocolSchedule, + metricsSystem) -> new ClassicBlockProcessor( transactionProcessor, transactionReceiptFactory, @@ -115,7 +116,8 @@ public static ProtocolSpecBuilder gothamDefinition( miningBeneficiaryCalculator, skipZeroBlockRewards, ecip1017EraRounds, - protocolSchedule)) + protocolSchedule, + metricsSystem)) .name("Gotham"); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockProcessor.java index 9f2096f63d2..dc66b905906 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockProcessor.java @@ -20,6 +20,7 @@ import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.evm.account.MutableAccount; import org.hyperledger.besu.evm.worldstate.WorldUpdater; +import org.hyperledger.besu.plugin.services.MetricsSystem; import java.util.List; @@ -36,14 +37,16 @@ public MainnetBlockProcessor( final Wei blockReward, final MiningBeneficiaryCalculator miningBeneficiaryCalculator, final boolean skipZeroBlockRewards, - final ProtocolSchedule protocolSchedule) { + final ProtocolSchedule protocolSchedule, + final MetricsSystem metricsSystem) { super( transactionProcessor, transactionReceiptFactory, blockReward, miningBeneficiaryCalculator, skipZeroBlockRewards, - protocolSchedule); + protocolSchedule, + metricsSystem); } @Override diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSchedule.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSchedule.java index 921a0a16dca..0f27bfdc586 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSchedule.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSchedule.java @@ -19,8 +19,11 @@ import org.hyperledger.besu.ethereum.difficulty.fixed.FixedDifficultyCalculators; import org.hyperledger.besu.ethereum.difficulty.fixed.FixedDifficultyProtocolSchedule; import org.hyperledger.besu.evm.internal.EvmConfiguration; +import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; +import org.hyperledger.besu.plugin.services.MetricsSystem; import java.math.BigInteger; +import java.util.Optional; import java.util.function.Function; /** Provides {@link ProtocolSpec} lookups for mainnet hard forks. */ @@ -42,21 +45,46 @@ public static ProtocolSchedule fromConfig( final GenesisConfigOptions config, final PrivacyParameters privacyParameters, final boolean isRevertReasonEnabled, - final EvmConfiguration evmConfiguration) { + final EvmConfiguration evmConfiguration, + final MetricsSystem metricsSystem) { if (FixedDifficultyCalculators.isFixedDifficultyInConfig(config)) { return FixedDifficultyProtocolSchedule.create( config, privacyParameters, isRevertReasonEnabled, evmConfiguration); } return new ProtocolScheduleBuilder( config, - DEFAULT_CHAIN_ID, + Optional.of(DEFAULT_CHAIN_ID), ProtocolSpecAdapters.create(0, Function.identity()), privacyParameters, isRevertReasonEnabled, - evmConfiguration) + evmConfiguration, + metricsSystem) .createProtocolSchedule(); } + /** + * Create a Mainnet protocol schedule from a config object + * + * @param config {@link GenesisConfigOptions} containing the config options for the milestone + * starting points + * @param privacyParameters the parameters set for private transactions + * @param isRevertReasonEnabled whether storing the revert reason is for failed transactions + * @param evmConfiguration how to configure the EVMs jumpdest cache + * @return A configured mainnet protocol schedule + */ + public static ProtocolSchedule fromConfig( + final GenesisConfigOptions config, + final PrivacyParameters privacyParameters, + final boolean isRevertReasonEnabled, + final EvmConfiguration evmConfiguration) { + return fromConfig( + config, + privacyParameters, + isRevertReasonEnabled, + evmConfiguration, + new NoOpMetricsSystem()); + } + /** * Create a Mainnet protocol schedule from a config object * diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java index e477bf6f75e..e1b13a23f75 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.ethereum.mainnet; +import static java.util.Objects.requireNonNull; + import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.config.PowAlgorithm; import org.hyperledger.besu.datatypes.Address; @@ -217,7 +219,8 @@ public static ProtocolSpecBuilder daoRecoveryInitDefinition( blockReward, miningBeneficiaryCalculator, skipZeroBlockRewards, - protocolSchedule) -> + protocolSchedule, + metricsSystem) -> new DaoBlockProcessor( new MainnetBlockProcessor( transactionProcessor, @@ -225,7 +228,8 @@ public static ProtocolSpecBuilder daoRecoveryInitDefinition( blockReward, miningBeneficiaryCalculator, skipZeroBlockRewards, - protocolSchedule))) + protocolSchedule, + metricsSystem))) .name("DaoRecoveryInit"); } @@ -863,7 +867,8 @@ private void updateWorldStateForDao(final MutableWorldState worldState) { final JsonArray json = new JsonArray( Resources.toString( - this.getClass().getResource("/daoAddresses.json"), StandardCharsets.UTF_8)); + requireNonNull(this.getClass().getResource("/daoAddresses.json")), + StandardCharsets.UTF_8)); final List

addresses = IntStream.range(0, json.size()) .mapToObj(json::getString) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MetricsOperationTracer.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MetricsOperationTracer.java new file mode 100644 index 00000000000..bf9b9b8eb13 --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MetricsOperationTracer.java @@ -0,0 +1,100 @@ +/* + * Copyright contributors to Hyperledger Besu + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.mainnet; + +import org.hyperledger.besu.evm.frame.MessageFrame; +import org.hyperledger.besu.evm.operation.Operation; +import org.hyperledger.besu.evm.operation.Operation.OperationResult; +import org.hyperledger.besu.evm.tracing.OperationTracer; +import org.hyperledger.besu.metrics.BesuMetricCategory; +import org.hyperledger.besu.plugin.services.MetricsSystem; +import org.hyperledger.besu.plugin.services.metrics.Counter; +import org.hyperledger.besu.plugin.services.metrics.LabelledMetric; + +import org.apache.tuweni.bytes.Bytes; + +public class MetricsOperationTracer implements OperationTracer { + + private static final String[] opcodes = { + "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", + "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", + "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", + "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", + "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", + "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", + "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", + "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", + "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", + "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", + "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", + "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", + "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", + "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", + "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff", + }; + + static LabelledMetric opcodeCounter; + static LabelledMetric opcodeGasCounter; + static LabelledMetric precompileCounter; + static LabelledMetric precompileGasCounter; + + @SuppressWarnings("StaticAssignmentInConstructor") + public MetricsOperationTracer(final MetricsSystem metricsSystem) { + if (opcodeCounter == null) { + opcodeCounter = + metricsSystem.createLabelledCounter( + BesuMetricCategory.EVM, + "evm_operations", + "invocation count of opcodes", + "opcode_hex"); + opcodeGasCounter = + metricsSystem.createLabelledCounter( + BesuMetricCategory.EVM, + "evm_operations_gas", + "invocation gas usage of opcodes", + "opcode_hex"); + precompileCounter = + metricsSystem.createLabelledCounter( + BesuMetricCategory.EVM, + "evm_precompile", + "invocation count of precompiles", + "contract"); + precompileGasCounter = + metricsSystem.createLabelledCounter( + BesuMetricCategory.EVM, + "evm_precompile_gas", + "invocation gas usage of precompiles", + "contract"); + } + } + + @Override + public void tracePostExecution(final MessageFrame frame, final OperationResult operationResult) { + final Operation currentOp = frame.getCurrentOperation(); + final int opcode = currentOp.getOpcode(); + String opcodeString = opcodes[opcode]; + opcodeCounter.labels(opcodeString).inc(); + opcodeGasCounter.labels(opcodeString).inc(operationResult.getGasCost()); + } + + @Override + public void tracePrecompileCall( + final MessageFrame frame, final long gasRequirement, final Bytes output) { + String contractAddress = frame.getContractAddress().toShortHexString(); + precompileCounter.labels(contractAddress).inc(); + precompileGasCounter.labels(contractAddress).inc(gasRequirement); + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java index 519450b42fc..c9191f27aaf 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java @@ -19,6 +19,8 @@ import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.privacy.PrivateTransactionValidator; import org.hyperledger.besu.evm.internal.EvmConfiguration; +import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; +import org.hyperledger.besu.plugin.services.MetricsSystem; import java.math.BigInteger; import java.util.Optional; @@ -41,8 +43,7 @@ public class ProtocolScheduleBuilder { private final boolean isRevertReasonEnabled; private final EvmConfiguration evmConfiguration; private final BadBlockManager badBlockManager = new BadBlockManager(); - - private DefaultProtocolSchedule protocolSchedule; + private final MetricsSystem metricsSystem; public ProtocolScheduleBuilder( final GenesisConfigOptions config, @@ -57,7 +58,8 @@ public ProtocolScheduleBuilder( protocolSpecAdapters, privacyParameters, isRevertReasonEnabled, - evmConfiguration); + evmConfiguration, + new NoOpMetricsSystem()); } public ProtocolScheduleBuilder( @@ -72,27 +74,30 @@ public ProtocolScheduleBuilder( protocolSpecAdapters, privacyParameters, isRevertReasonEnabled, - evmConfiguration); + evmConfiguration, + new NoOpMetricsSystem()); } - private ProtocolScheduleBuilder( + ProtocolScheduleBuilder( final GenesisConfigOptions config, final Optional defaultChainId, final ProtocolSpecAdapters protocolSpecAdapters, final PrivacyParameters privacyParameters, final boolean isRevertReasonEnabled, - final EvmConfiguration evmConfiguration) { + final EvmConfiguration evmConfiguration, + final MetricsSystem metricsSystem) { this.config = config; this.protocolSpecAdapters = protocolSpecAdapters; this.privacyParameters = privacyParameters; this.isRevertReasonEnabled = isRevertReasonEnabled; this.evmConfiguration = evmConfiguration; this.defaultChainId = defaultChainId; + this.metricsSystem = metricsSystem; } public ProtocolSchedule createProtocolSchedule() { final Optional chainId = config.getChainId().or(() -> defaultChainId); - protocolSchedule = new DefaultProtocolSchedule(chainId); + DefaultProtocolSchedule protocolSchedule = new DefaultProtocolSchedule(chainId); initSchedule(protocolSchedule, chainId); return protocolSchedule; } @@ -127,10 +132,7 @@ private void initSchedule( builders.put( modifierBlock, new BuilderMapEntry( - parent.milestoneType, - modifierBlock, - parent.getBuilder(), - entry.getValue())); + parent.milestoneType, modifierBlock, parent.builder(), entry.getValue())); }); } @@ -142,8 +144,8 @@ private void initSchedule( addProtocolSpec( protocolSchedule, e.milestoneType, - e.getBlockIdentifier(), - e.getBuilder(), + e.blockIdentifier(), + e.builder(), e.modifier)); // NOTE: It is assumed that Daofork blocks will not be used for private networks @@ -157,8 +159,8 @@ private void initSchedule( final ProtocolSpec originalProtocolSpec = getProtocolSpec( protocolSchedule, - previousSpecBuilder.getBuilder(), - previousSpecBuilder.getModifier()); + previousSpecBuilder.builder(), + previousSpecBuilder.modifier()); addProtocolSpec( protocolSchedule, BuilderMapEntry.MilestoneType.BLOCK_NUMBER, @@ -185,8 +187,8 @@ private void initSchedule( final ProtocolSpec originalProtocolSpec = getProtocolSpec( protocolSchedule, - previousSpecBuilder.getBuilder(), - previousSpecBuilder.getModifier()); + previousSpecBuilder.builder(), + previousSpecBuilder.modifier()); addProtocolSpec( protocolSchedule, BuilderMapEntry.MilestoneType.BLOCK_NUMBER, @@ -280,7 +282,7 @@ private TreeMap buildMilestoneMap( .flatMap(Optional::stream) .collect( Collectors.toMap( - BuilderMapEntry::getBlockIdentifier, + BuilderMapEntry::blockIdentifier, b -> b, (existing, replacement) -> replacement, TreeMap::new)); @@ -379,9 +381,11 @@ private void addProtocolSpec( switch (milestoneType) { case BLOCK_NUMBER -> protocolSchedule.putBlockNumberMilestone( - blockNumberOrTimestamp, getProtocolSpec(protocolSchedule, definition, modifier)); + blockNumberOrTimestamp, + getProtocolSpec(protocolSchedule, definition.metricsSystem(metricsSystem), modifier)); case TIMESTAMP -> protocolSchedule.putTimestampMilestone( - blockNumberOrTimestamp, getProtocolSpec(protocolSchedule, definition, modifier)); + blockNumberOrTimestamp, + getProtocolSpec(protocolSchedule, definition.metricsSystem(metricsSystem), modifier)); default -> throw new IllegalStateException( "Unexpected milestoneType: " + milestoneType @@ -390,34 +394,11 @@ private void addProtocolSpec( } } - private static class BuilderMapEntry { - private final MilestoneType milestoneType; - private final long blockIdentifier; - private final ProtocolSpecBuilder builder; - private final Function modifier; - - public BuilderMapEntry( - final MilestoneType milestoneType, - final long blockIdentifier, - final ProtocolSpecBuilder builder, - final Function modifier) { - this.milestoneType = milestoneType; - this.blockIdentifier = blockIdentifier; - this.builder = builder; - this.modifier = modifier; - } - - public long getBlockIdentifier() { - return blockIdentifier; - } - - public ProtocolSpecBuilder getBuilder() { - return builder; - } - - public Function getModifier() { - return modifier; - } + private record BuilderMapEntry( + ProtocolScheduleBuilder.BuilderMapEntry.MilestoneType milestoneType, + long blockIdentifier, + ProtocolSpecBuilder builder, + Function modifier) { private enum MilestoneType { BLOCK_NUMBER, diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolSpecBuilder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolSpecBuilder.java index 7b39ebe2f5f..1abf065a68e 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolSpecBuilder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolSpecBuilder.java @@ -37,6 +37,8 @@ import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.precompile.PrecompileContractRegistry; import org.hyperledger.besu.evm.processor.AbstractMessageProcessor; +import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; +import org.hyperledger.besu.plugin.services.MetricsSystem; import java.util.Optional; import java.util.function.BiFunction; @@ -78,9 +80,9 @@ public class ProtocolSpecBuilder { private DepositsValidator depositsValidator = new DepositsValidator.ProhibitedDeposits(); private FeeMarket feeMarket = FeeMarket.legacy(); private BadBlockManager badBlockManager; - private PoWHasher powHasher = PoWHasher.ETHASH_LIGHT; private boolean isPoS = false; private boolean isReplayProtectionSupported = false; + private MetricsSystem metricsSystem = new NoOpMetricsSystem(); public ProtocolSpecBuilder gasCalculator(final Supplier gasCalculatorBuilder) { this.gasCalculatorBuilder = gasCalculatorBuilder; @@ -240,11 +242,6 @@ public ProtocolSpecBuilder badBlocksManager(final BadBlockManager badBlockManage return this; } - public ProtocolSpecBuilder powHasher(final PoWHasher powHasher) { - this.powHasher = powHasher; - return this; - } - public ProtocolSpecBuilder evmConfiguration(final EvmConfiguration evmConfiguration) { this.evmConfiguration = evmConfiguration; return this; @@ -276,6 +273,11 @@ public ProtocolSpecBuilder isReplayProtectionSupported( return this; } + public ProtocolSpecBuilder metricsSystem(final MetricsSystem metricsSystem) { + this.metricsSystem = metricsSystem; + return this; + } + public ProtocolSpec build(final ProtocolSchedule protocolSchedule) { checkNotNull(gasCalculatorBuilder, "Missing gasCalculator"); checkNotNull(gasLimitCalculatorBuilder, "Missing gasLimitCalculatorBuilder"); @@ -333,7 +335,8 @@ public ProtocolSpec build(final ProtocolSchedule protocolSchedule) { final BlockBodyValidator blockBodyValidator = blockBodyValidatorBuilder.apply(protocolSchedule); - BlockProcessor blockProcessor = createBlockProcessor(transactionProcessor, protocolSchedule); + BlockProcessor blockProcessor = + createBlockProcessor(transactionProcessor, protocolSchedule, metricsSystem); // Set private Tx Processor PrivateTransactionProcessor privateTransactionProcessor = createPrivateTransactionProcessor( @@ -381,7 +384,7 @@ public ProtocolSpec build(final ProtocolSchedule protocolSchedule) { gasLimitCalculator, feeMarket, badBlockManager, - Optional.ofNullable(powHasher), + Optional.of(PoWHasher.ETHASH_LIGHT), withdrawalsValidator, Optional.ofNullable(withdrawalsProcessor), depositsValidator, @@ -426,14 +429,16 @@ private PrivateTransactionProcessor createPrivateTransactionProcessor( private BlockProcessor createBlockProcessor( final MainnetTransactionProcessor transactionProcessor, - final ProtocolSchedule protocolSchedule) { + final ProtocolSchedule protocolSchedule, + final MetricsSystem metricsSystem) { return blockProcessorBuilder.apply( transactionProcessor, transactionReceiptFactory, blockReward, miningBeneficiaryCalculator, skipZeroBlockRewards, - protocolSchedule); + protocolSchedule, + metricsSystem); } private BlockHeaderValidator createBlockHeaderValidator( @@ -472,7 +477,8 @@ BlockProcessor apply( Wei blockReward, MiningBeneficiaryCalculator miningBeneficiaryCalculator, boolean skipZeroBlockRewards, - ProtocolSchedule protocolSchedule); + ProtocolSchedule protocolSchedule, + MetricsSystem metricsSystem); } public interface BlockValidatorBuilder { diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java index a33f6a2b04e..c6d9b90a8f1 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java @@ -71,7 +71,8 @@ class BlockImportExceptionHandlingTest { Wei.ZERO, BlockHeader::getCoinbase, true, - protocolSchedule); + protocolSchedule, + new NoOpMetricsSystem()); private final BlockHeaderValidator blockHeaderValidator = mock(BlockHeaderValidator.class); private final BlockBodyValidator blockBodyValidator = mock(BlockBodyValidator.class); private final ProtocolContext protocolContext = mock(ProtocolContext.class); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessorTest.java index 867bfeb7e5f..2d479241a37 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessorTest.java @@ -34,6 +34,7 @@ import org.hyperledger.besu.ethereum.core.Withdrawal; import org.hyperledger.besu.ethereum.referencetests.ReferenceTestBlockchain; import org.hyperledger.besu.ethereum.referencetests.ReferenceTestWorldState; +import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import java.util.List; import java.util.Optional; @@ -156,7 +157,8 @@ protected TestBlockProcessor( blockReward, miningBeneficiaryCalculator, skipZeroBlockRewards, - protocolSchedule); + protocolSchedule, + new NoOpMetricsSystem()); } @Override diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockProcessorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockProcessorTest.java index 1b106686bfc..4b10242b6be 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockProcessorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockProcessorTest.java @@ -29,6 +29,7 @@ import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.referencetests.ReferenceTestBlockchain; import org.hyperledger.besu.ethereum.referencetests.ReferenceTestWorldState; +import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -60,7 +61,8 @@ public void noAccountCreatedWhenBlockRewardIsZeroAndSkipped() { Wei.ZERO, BlockHeader::getCoinbase, true, - protocolSchedule); + protocolSchedule, + new NoOpMetricsSystem()); final MutableWorldState worldState = ReferenceTestWorldState.create(emptyMap()); final Hash initialHash = worldState.rootHash(); @@ -86,7 +88,8 @@ public void accountCreatedWhenBlockRewardIsZeroAndNotSkipped() { Wei.ZERO, BlockHeader::getCoinbase, false, - protocolSchedule); + protocolSchedule, + new NoOpMetricsSystem()); final MutableWorldState worldState = ReferenceTestWorldState.create(emptyMap()); final Hash initialHash = worldState.rootHash(); diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/NoRewardProtocolScheduleWrapper.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/NoRewardProtocolScheduleWrapper.java index f4ad7774058..01117d452df 100644 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/NoRewardProtocolScheduleWrapper.java +++ b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/NoRewardProtocolScheduleWrapper.java @@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.ScheduledProtocolSpec; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; +import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import java.math.BigInteger; import java.util.Optional; @@ -51,7 +52,8 @@ public ProtocolSpec getByBlockHeader(final ProcessableBlockHeader blockHeader) { Wei.ZERO, original.getMiningBeneficiaryCalculator(), original.isSkipZeroBlockRewards(), - delegate); + delegate, + new NoOpMetricsSystem()); final BlockValidator noRewardBlockValidator = new MainnetBlockValidator( original.getBlockHeaderValidator(), diff --git a/metrics/core/src/main/java/org/hyperledger/besu/metrics/BesuMetricCategory.java b/metrics/core/src/main/java/org/hyperledger/besu/metrics/BesuMetricCategory.java index 27be3ff9321..fde24664e37 100644 --- a/metrics/core/src/main/java/org/hyperledger/besu/metrics/BesuMetricCategory.java +++ b/metrics/core/src/main/java/org/hyperledger/besu/metrics/BesuMetricCategory.java @@ -53,7 +53,8 @@ public enum BesuMetricCategory implements MetricCategory { /** Transaction pool besu metric category. */ TRANSACTION_POOL("transaction_pool"), /** Stratum besu metric category. */ - STRATUM("stratum"); + STRATUM("stratum"), + EVM("evm"); private static final Optional BESU_PREFIX = Optional.of("besu_"); /** The constant DEFAULT_METRIC_CATEGORIES. */