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 ae661f6fa5..4e2519056f 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -60,6 +60,8 @@ import org.hyperledger.besu.cli.util.CommandLineUtils; import org.hyperledger.besu.cli.util.ConfigOptionSearchAndRunHandler; import org.hyperledger.besu.cli.util.VersionProvider; import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.consensus.common.PoAContext; +import org.hyperledger.besu.consensus.common.PoAMetricServiceImpl; import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.controller.BesuControllerBuilder; import org.hyperledger.besu.controller.KeyPairUtil; @@ -86,6 +88,7 @@ import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProvider; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder; import org.hyperledger.besu.ethereum.worldstate.PruningConfiguration; import org.hyperledger.besu.metrics.BesuMetricCategory; +import org.hyperledger.besu.metrics.MetricCategoryRegistryImpl; import org.hyperledger.besu.metrics.ObservableMetricsSystem; import org.hyperledger.besu.metrics.StandardMetricCategory; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; @@ -99,6 +102,8 @@ import org.hyperledger.besu.plugin.services.PicoCLIOptions; import org.hyperledger.besu.plugin.services.StorageService; import org.hyperledger.besu.plugin.services.exception.StorageException; import org.hyperledger.besu.plugin.services.metrics.MetricCategory; +import org.hyperledger.besu.plugin.services.metrics.MetricCategoryRegistry; +import org.hyperledger.besu.plugin.services.metrics.PoAMetricsService; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBPlugin; import org.hyperledger.besu.services.BesuConfigurationImpl; import org.hyperledger.besu.services.BesuEventsImpl; @@ -185,6 +190,9 @@ public class BesuCommand implements DefaultCommandValues, Runnable { private final BesuPluginContextImpl besuPluginContext; private final StorageServiceImpl storageService; private final Map environment; + private final MetricCategoryRegistryImpl metricCategoryRegistry = + new MetricCategoryRegistryImpl(); + private final MetricCategoryConverter metricCategoryConverter = new MetricCategoryConverter(); protected KeyLoader getKeyLoader() { return KeyPairUtil::loadKeyPair; @@ -822,7 +830,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable { commandLine.registerConverter(Wei.class, (arg) -> Wei.of(Long.parseUnsignedLong(arg))); commandLine.registerConverter(PositiveNumber.class, PositiveNumber::fromString); - final MetricCategoryConverter metricCategoryConverter = new MetricCategoryConverter(); metricCategoryConverter.addCategories(BesuMetricCategory.class); metricCategoryConverter.addCategories(StandardMetricCategory.class); commandLine.registerConverter(MetricCategory.class, metricCategoryConverter); @@ -848,11 +855,17 @@ public class BesuCommand implements DefaultCommandValues, Runnable { private BesuCommand preparePlugins() { besuPluginContext.addService(PicoCLIOptions.class, new PicoCLIOptionsImpl(commandLine)); besuPluginContext.addService(StorageService.class, storageService); + besuPluginContext.addService(MetricCategoryRegistry.class, metricCategoryRegistry); // register built-in plugins new RocksDBPlugin().register(besuPluginContext); besuPluginContext.registerPlugins(pluginsDir()); + + metricCategoryRegistry + .getMetricCategories() + .forEach(metricCategoryConverter::addRegistryCategory); + return this; } @@ -894,11 +907,25 @@ public class BesuCommand implements DefaultCommandValues, Runnable { besuController.getProtocolManager().getBlockBroadcaster(), besuController.getTransactionPool(), besuController.getSyncState())); - besuPluginContext.addService(MetricsSystem.class, getMetricsSystem()); + addPluginMetrics(besuController); besuPluginContext.startPlugins(); return this; } + private void addPluginMetrics(final BesuController besuController) { + besuPluginContext.addService(MetricsSystem.class, getMetricsSystem()); + + final Object consensusState = besuController.getProtocolContext().getConsensusState(); + + if (consensusState != null && PoAContext.class.isAssignableFrom(consensusState.getClass())) { + final PoAMetricServiceImpl service = + new PoAMetricServiceImpl( + ((PoAContext) consensusState).getBlockInterface(), + besuController.getProtocolContext().getBlockchain()); + besuPluginContext.addService(PoAMetricsService.class, service); + } + } + private void prepareLogging() { // set log level per CLI flags if (logLevel != null) { diff --git a/besu/src/main/java/org/hyperledger/besu/cli/converter/MetricCategoryConverter.java b/besu/src/main/java/org/hyperledger/besu/cli/converter/MetricCategoryConverter.java index bf4ac57a96..0d1f0ad223 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/converter/MetricCategoryConverter.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/converter/MetricCategoryConverter.java @@ -39,4 +39,8 @@ public class MetricCategoryConverter implements CommandLine.ITypeConverter metricCategories.put(category.name(), category)); } + + public void addRegistryCategory(final MetricCategory metricCategory) { + metricCategories.put(metricCategory.getName(), metricCategory); + } } diff --git a/besu/src/main/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilder.java index 85489860c4..1af2f0aab7 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilder.java @@ -148,6 +148,7 @@ public class CliqueBesuControllerBuilder extends BesuControllerBuilder extractVoteFromHeader(final BlockHeader header) { final Address candidate = header.getCoinbase(); diff --git a/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/CliqueContext.java b/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/CliqueContext.java index 5de07e4aa5..f54eaca00b 100644 --- a/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/CliqueContext.java +++ b/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/CliqueContext.java @@ -14,7 +14,9 @@ */ package org.hyperledger.besu.consensus.clique; +import org.hyperledger.besu.consensus.common.BlockInterface; import org.hyperledger.besu.consensus.common.EpochManager; +import org.hyperledger.besu.consensus.common.PoAContext; import org.hyperledger.besu.consensus.common.VoteProposer; import org.hyperledger.besu.consensus.common.VoteTallyCache; @@ -22,19 +24,22 @@ import org.hyperledger.besu.consensus.common.VoteTallyCache; * Holds the data which lives "in parallel" with the importation of blocks etc. when using the * Clique consensus mechanism. */ -public class CliqueContext { +public class CliqueContext implements PoAContext { private final VoteTallyCache voteTallyCache; private final VoteProposer voteProposer; private final EpochManager epochManager; + private final BlockInterface blockInterface; public CliqueContext( final VoteTallyCache voteTallyCache, final VoteProposer voteProposer, - final EpochManager epochManager) { + final EpochManager epochManager, + final BlockInterface blockInterface) { this.voteTallyCache = voteTallyCache; this.voteProposer = voteProposer; this.epochManager = epochManager; + this.blockInterface = blockInterface; } public VoteTallyCache getVoteTallyCache() { @@ -48,4 +53,9 @@ public class CliqueContext { public EpochManager getEpochManager() { return epochManager; } + + @Override + public BlockInterface getBlockInterface() { + return blockInterface; + } } diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/CliqueDifficultyCalculatorTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/CliqueDifficultyCalculatorTest.java index d772c8b6e8..5d355e5a97 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/CliqueDifficultyCalculatorTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/CliqueDifficultyCalculatorTest.java @@ -45,6 +45,7 @@ public class CliqueDifficultyCalculatorTest { private final List
validatorList = Lists.newArrayList(); private ProtocolContext cliqueProtocolContext; private BlockHeaderTestFixture blockHeaderBuilder; + private final CliqueBlockInterface blockInterface = new CliqueBlockInterface(); @Before public void setup() { @@ -57,7 +58,8 @@ public class CliqueDifficultyCalculatorTest { when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList)); final VoteProposer voteProposer = new VoteProposer(); - final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null); + final CliqueContext cliqueContext = + new CliqueContext(voteTallyCache, voteProposer, null, blockInterface); cliqueProtocolContext = new ProtocolContext<>(null, null, cliqueContext); blockHeaderBuilder = new BlockHeaderTestFixture(); } diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/NodeCanProduceNextBlockTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/NodeCanProduceNextBlockTest.java index a049a513c1..9fc1b04b90 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/NodeCanProduceNextBlockTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/NodeCanProduceNextBlockTest.java @@ -51,6 +51,7 @@ public class NodeCanProduceNextBlockTest { private final List
validatorList = Lists.newArrayList(); private final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); private ProtocolContext cliqueProtocolContext; + private final CliqueBlockInterface blockInterface = new CliqueBlockInterface(); MutableBlockchain blockChain; private Block genesisBlock; @@ -78,7 +79,8 @@ public class NodeCanProduceNextBlockTest { final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class); when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList)); final VoteProposer voteProposer = new VoteProposer(); - final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null); + final CliqueContext cliqueContext = + new CliqueContext(voteTallyCache, voteProposer, null, blockInterface); cliqueProtocolContext = new ProtocolContext<>(blockChain, null, cliqueContext); headerBuilder.number(1).parentHash(genesisBlock.getHash()); @@ -103,7 +105,8 @@ public class NodeCanProduceNextBlockTest { final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class); when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList)); final VoteProposer voteProposer = new VoteProposer(); - final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null); + final CliqueContext cliqueContext = + new CliqueContext(voteTallyCache, voteProposer, null, blockInterface); cliqueProtocolContext = new ProtocolContext<>(blockChain, null, cliqueContext); headerBuilder.number(1).parentHash(genesisBlock.getHash()); @@ -137,7 +140,8 @@ public class NodeCanProduceNextBlockTest { final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class); when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList)); final VoteProposer voteProposer = new VoteProposer(); - final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null); + final CliqueContext cliqueContext = + new CliqueContext(voteTallyCache, voteProposer, null, blockInterface); cliqueProtocolContext = new ProtocolContext<>(blockChain, null, cliqueContext); headerBuilder.parentHash(genesisBlock.getHash()).number(1); @@ -167,7 +171,8 @@ public class NodeCanProduceNextBlockTest { final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class); when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList)); final VoteProposer voteProposer = new VoteProposer(); - final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null); + final CliqueContext cliqueContext = + new CliqueContext(voteTallyCache, voteProposer, null, blockInterface); cliqueProtocolContext = new ProtocolContext<>(blockChain, null, cliqueContext); headerBuilder.parentHash(genesisBlock.getHash()).number(1); @@ -212,7 +217,8 @@ public class NodeCanProduceNextBlockTest { final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class); when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList)); final VoteProposer voteProposer = new VoteProposer(); - final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null); + final CliqueContext cliqueContext = + new CliqueContext(voteTallyCache, voteProposer, null, blockInterface); cliqueProtocolContext = new ProtocolContext<>(blockChain, null, cliqueContext); headerBuilder.parentHash(genesisBlock.getHash()).number(1); @@ -241,7 +247,8 @@ public class NodeCanProduceNextBlockTest { final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class); when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList)); final VoteProposer voteProposer = new VoteProposer(); - final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null); + final CliqueContext cliqueContext = + new CliqueContext(voteTallyCache, voteProposer, null, blockInterface); cliqueProtocolContext = new ProtocolContext<>(blockChain, null, cliqueContext); headerBuilder.parentHash(Hash.ZERO).number(3); @@ -265,7 +272,8 @@ public class NodeCanProduceNextBlockTest { final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class); when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList)); final VoteProposer voteProposer = new VoteProposer(); - final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null); + final CliqueContext cliqueContext = + new CliqueContext(voteTallyCache, voteProposer, null, blockInterface); cliqueProtocolContext = new ProtocolContext<>(blockChain, null, cliqueContext); headerBuilder.parentHash(Hash.ZERO).number(3); diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java index cf0dac9539..e0ecd32ebc 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java @@ -66,6 +66,7 @@ public class CliqueBlockCreatorTest { private final KeyPair otherKeyPair = KeyPair.generate(); private final List
validatorList = Lists.newArrayList(); private final MetricsSystem metricsSystem = new NoOpMetricsSystem(); + private final CliqueBlockInterface blockInterface = new CliqueBlockInterface(); private ProtocolSchedule protocolSchedule; private final WorldStateArchive stateArchive = createInMemoryWorldStateArchive(); @@ -87,7 +88,8 @@ public class CliqueBlockCreatorTest { final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class); when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList)); voteProposer = new VoteProposer(); - final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null); + final CliqueContext cliqueContext = + new CliqueContext(voteTallyCache, voteProposer, null, blockInterface); final Block genesis = GenesisState.fromConfig(GenesisConfigFile.mainnet(), protocolSchedule).getBlock(); diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java index 92c57fd58c..f329921bd4 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java @@ -22,6 +22,7 @@ import static org.mockito.Mockito.when; import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.consensus.clique.CliqueBlockHeaderFunctions; +import org.hyperledger.besu.consensus.clique.CliqueBlockInterface; import org.hyperledger.besu.consensus.clique.CliqueContext; import org.hyperledger.besu.consensus.clique.CliqueExtraData; import org.hyperledger.besu.consensus.clique.CliqueProtocolSchedule; @@ -65,6 +66,7 @@ public class CliqueMinerExecutorTest { private ProtocolContext cliqueProtocolContext; private BlockHeaderTestFixture blockHeaderBuilder; private final MetricsSystem metricsSystem = new NoOpMetricsSystem(); + private final CliqueBlockInterface blockInterface = new CliqueBlockInterface(); @Before public void setup() { @@ -78,7 +80,8 @@ public class CliqueMinerExecutorTest { when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList)); final VoteProposer voteProposer = new VoteProposer(); - final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null); + final CliqueContext cliqueContext = + new CliqueContext(voteTallyCache, voteProposer, null, blockInterface); cliqueProtocolContext = new ProtocolContext<>(null, null, cliqueContext); blockHeaderBuilder = new BlockHeaderTestFixture(); } diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMiningCoordinatorTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMiningCoordinatorTest.java index b863207cab..919d3602de 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMiningCoordinatorTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMiningCoordinatorTest.java @@ -24,6 +24,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import org.hyperledger.besu.consensus.clique.CliqueBlockInterface; import org.hyperledger.besu.consensus.clique.CliqueContext; import org.hyperledger.besu.consensus.clique.CliqueMiningTracker; import org.hyperledger.besu.consensus.clique.TestHelpers; @@ -64,6 +65,7 @@ public class CliqueMiningCoordinatorTest { private final BlockHeaderTestFixture headerTestFixture = new BlockHeaderTestFixture(); private CliqueMiningTracker miningTracker; + private final CliqueBlockInterface blockInterface = new CliqueBlockInterface(); @Mock private MutableBlockchain blockChain; @Mock private ProtocolContext protocolContext; @@ -82,7 +84,8 @@ public class CliqueMiningCoordinatorTest { final VoteTally voteTally = mock(VoteTally.class); when(voteTally.getValidators()).thenReturn(validators); when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(voteTally); - final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, null, null); + final CliqueContext cliqueContext = + new CliqueContext(voteTallyCache, null, null, blockInterface); when(protocolContext.getConsensusState()).thenReturn(cliqueContext); when(protocolContext.getBlockchain()).thenReturn(blockChain); diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueDifficultyValidationRuleTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueDifficultyValidationRuleTest.java index c73f315285..1a869a5e8c 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueDifficultyValidationRuleTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueDifficultyValidationRuleTest.java @@ -19,6 +19,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import org.hyperledger.besu.consensus.clique.CliqueBlockInterface; import org.hyperledger.besu.consensus.clique.CliqueContext; import org.hyperledger.besu.consensus.clique.TestHelpers; import org.hyperledger.besu.consensus.common.VoteProposer; @@ -45,6 +46,7 @@ public class CliqueDifficultyValidationRuleTest { private final List
validatorList = Lists.newArrayList(); private ProtocolContext cliqueProtocolContext; private BlockHeaderTestFixture blockHeaderBuilder; + private final CliqueBlockInterface blockInterface = new CliqueBlockInterface(); @Before public void setup() { @@ -56,7 +58,8 @@ public class CliqueDifficultyValidationRuleTest { when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList)); final VoteProposer voteProposer = new VoteProposer(); - final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null); + final CliqueContext cliqueContext = + new CliqueContext(voteTallyCache, voteProposer, null, blockInterface); cliqueProtocolContext = new ProtocolContext<>(null, null, cliqueContext); blockHeaderBuilder = new BlockHeaderTestFixture(); } diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueExtraDataValidationRuleTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueExtraDataValidationRuleTest.java index 89b2d36311..910fcdcec6 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueExtraDataValidationRuleTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueExtraDataValidationRuleTest.java @@ -19,6 +19,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import org.hyperledger.besu.consensus.clique.CliqueBlockInterface; import org.hyperledger.besu.consensus.clique.CliqueContext; import org.hyperledger.besu.consensus.clique.CliqueExtraData; import org.hyperledger.besu.consensus.clique.TestHelpers; @@ -44,6 +45,7 @@ public class CliqueExtraDataValidationRuleTest { private final KeyPair proposerKeyPair = KeyPair.generate(); private Address localAddr; + private final CliqueBlockInterface blockInterface = new CliqueBlockInterface(); private final List
validatorList = Lists.newArrayList(); private ProtocolContext cliqueProtocolContext; @@ -58,7 +60,8 @@ public class CliqueExtraDataValidationRuleTest { final VoteTallyCache voteTallyCache = mock(VoteTallyCache.class); when(voteTallyCache.getVoteTallyAfterBlock(any())).thenReturn(new VoteTally(validatorList)); - final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, null, null); + final CliqueContext cliqueContext = + new CliqueContext(voteTallyCache, null, null, blockInterface); cliqueProtocolContext = new ProtocolContext<>(null, null, cliqueContext); } diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/BlockInterface.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/BlockInterface.java index 963875580e..ee9af867ef 100644 --- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/BlockInterface.java +++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/BlockInterface.java @@ -22,7 +22,9 @@ import java.util.Optional; public interface BlockInterface { - Address getProposerOfBlock(final BlockHeader header); + Address getProposerOfBlock(final org.hyperledger.besu.ethereum.core.BlockHeader header); + + Address getProposerOfBlock(final org.hyperledger.besu.plugin.data.BlockHeader header); Optional extractVoteFromHeader(final BlockHeader header); diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/PoAContext.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/PoAContext.java new file mode 100644 index 0000000000..5a70d3f2a7 --- /dev/null +++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/PoAContext.java @@ -0,0 +1,19 @@ +/* + * Copyright ConsenSys AG. + * + * 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.consensus.common; + +public interface PoAContext { + BlockInterface getBlockInterface(); +} diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/PoAMetricServiceImpl.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/PoAMetricServiceImpl.java new file mode 100644 index 0000000000..bc5db07342 --- /dev/null +++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/PoAMetricServiceImpl.java @@ -0,0 +1,44 @@ +/* + * Copyright 2019 ConsenSys AG. + * + * 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.consensus.common; + +import org.hyperledger.besu.ethereum.chain.Blockchain; +import org.hyperledger.besu.plugin.data.Address; +import org.hyperledger.besu.plugin.data.BlockHeader; +import org.hyperledger.besu.plugin.services.metrics.PoAMetricsService; + +import java.util.ArrayList; +import java.util.Collection; + +public class PoAMetricServiceImpl implements PoAMetricsService { + + private final BlockInterface blockInterface; + private final Blockchain blockchain; + + public PoAMetricServiceImpl(final BlockInterface blockInterface, final Blockchain blockchain) { + this.blockInterface = blockInterface; + this.blockchain = blockchain; + } + + @Override + public Collection
getValidatorsForLatestBlock() { + return new ArrayList<>(blockInterface.validatorsInBlock(blockchain.getChainHeadHeader())); + } + + @Override + public Address getProposerOfBlock(final BlockHeader header) { + return this.blockInterface.getProposerOfBlock(header); + } +} diff --git a/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java b/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java index dc9c0c86a1..38f46a8342 100644 --- a/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java +++ b/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java @@ -284,7 +284,9 @@ public class TestContextBuilder { final ProtocolContext protocolContext = new ProtocolContext<>( - blockChain, worldStateArchive, new IbftContext(voteTallyCache, voteProposer)); + blockChain, + worldStateArchive, + new IbftContext(voteTallyCache, voteProposer, blockInterface)); final PendingTransactions pendingTransactions = new PendingTransactions( diff --git a/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/IbftBlockInterface.java b/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/IbftBlockInterface.java index ea882a3462..2cd5e9176c 100644 --- a/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/IbftBlockInterface.java +++ b/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/IbftBlockInterface.java @@ -33,6 +33,11 @@ public class IbftBlockInterface implements BlockInterface { return header.getCoinbase(); } + @Override + public Address getProposerOfBlock(final org.hyperledger.besu.plugin.data.BlockHeader header) { + return Address.fromHexString(header.getCoinbase().getHexString()); + } + @Override public Optional extractVoteFromHeader(final BlockHeader header) { final IbftExtraData ibftExtraData = IbftExtraData.decode(header); diff --git a/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/IbftContext.java b/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/IbftContext.java index f7126778b2..8127be3f80 100644 --- a/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/IbftContext.java +++ b/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/IbftContext.java @@ -14,18 +14,25 @@ */ package org.hyperledger.besu.consensus.ibft; +import org.hyperledger.besu.consensus.common.BlockInterface; +import org.hyperledger.besu.consensus.common.PoAContext; import org.hyperledger.besu.consensus.common.VoteProposer; import org.hyperledger.besu.consensus.common.VoteTallyCache; /** Holds the IBFT specific mutable state. */ -public class IbftContext { +public class IbftContext implements PoAContext { private final VoteTallyCache voteTallyCache; private final VoteProposer voteProposer; + private final BlockInterface blockInterface; - public IbftContext(final VoteTallyCache voteTallyCache, final VoteProposer voteProposer) { + public IbftContext( + final VoteTallyCache voteTallyCache, + final VoteProposer voteProposer, + final BlockInterface blockInterface) { this.voteTallyCache = voteTallyCache; this.voteProposer = voteProposer; + this.blockInterface = blockInterface; } public VoteTallyCache getVoteTallyCache() { @@ -35,4 +42,9 @@ public class IbftContext { public VoteProposer getVoteProposer() { return voteProposer; } + + @Override + public BlockInterface getBlockInterface() { + return blockInterface; + } } diff --git a/consensus/ibftlegacy/src/main/java/org/hyperledger/besu/consensus/ibftlegacy/IbftLegacyBlockInterface.java b/consensus/ibftlegacy/src/main/java/org/hyperledger/besu/consensus/ibftlegacy/IbftLegacyBlockInterface.java index fab0571aa6..7cdd2df3f6 100644 --- a/consensus/ibftlegacy/src/main/java/org/hyperledger/besu/consensus/ibftlegacy/IbftLegacyBlockInterface.java +++ b/consensus/ibftlegacy/src/main/java/org/hyperledger/besu/consensus/ibftlegacy/IbftLegacyBlockInterface.java @@ -46,6 +46,12 @@ public class IbftLegacyBlockInterface implements BlockInterface { return IbftBlockHashing.recoverProposerAddress(header, ibftExtraData); } + @Override + public Address getProposerOfBlock(final org.hyperledger.besu.plugin.data.BlockHeader header) { + return getProposerOfBlock( + BlockHeader.convertPluginBlockHeader(header, new LegacyIbftBlockHeaderFunctions())); + } + @Override public Optional extractVoteFromHeader(final BlockHeader header) { final Address candidate = header.getCoinbase(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java index 6c009ed3b6..a438bcd986 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java @@ -210,4 +210,27 @@ public class BlockHeader extends SealableBlockHeader sb.append("nonce=").append(nonce); return sb.append("}").toString(); } + + public static org.hyperledger.besu.ethereum.core.BlockHeader convertPluginBlockHeader( + final org.hyperledger.besu.plugin.data.BlockHeader pluginBlockHeader, + final BlockHeaderFunctions blockHeaderFunctions) { + return new org.hyperledger.besu.ethereum.core.BlockHeader( + Hash.fromHexString(pluginBlockHeader.getParentHash().getHexString()), + Hash.fromHexString(pluginBlockHeader.getOmmersHash().getHexString()), + org.hyperledger.besu.ethereum.core.Address.fromHexString( + pluginBlockHeader.getCoinbase().getHexString()), + Hash.fromHexString(pluginBlockHeader.getStateRoot().getHexString()), + Hash.fromHexString(pluginBlockHeader.getTransactionsRoot().getHexString()), + Hash.fromHexString(pluginBlockHeader.getReceiptsRoot().getHexString()), + LogsBloomFilter.fromHexString(pluginBlockHeader.getLogsBloom().getHexString()), + UInt256.fromHexString(pluginBlockHeader.getDifficulty().getHexString()), + pluginBlockHeader.getNumber(), + pluginBlockHeader.getGasLimit(), + pluginBlockHeader.getGasUsed(), + pluginBlockHeader.getTimestamp(), + BytesValue.wrap(pluginBlockHeader.getExtraData().getByteArray()), + Hash.fromHexString(pluginBlockHeader.getMixHash().getHexString()), + pluginBlockHeader.getNonce(), + blockHeaderFunctions); + } } diff --git a/metrics/core/src/main/java/org/hyperledger/besu/metrics/MetricCategoryRegistryImpl.java b/metrics/core/src/main/java/org/hyperledger/besu/metrics/MetricCategoryRegistryImpl.java new file mode 100644 index 0000000000..821c64c03d --- /dev/null +++ b/metrics/core/src/main/java/org/hyperledger/besu/metrics/MetricCategoryRegistryImpl.java @@ -0,0 +1,35 @@ +/* + * Copyright 2019 ConsenSys AG. + * + * 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.metrics; + +import org.hyperledger.besu.plugin.services.metrics.MetricCategory; +import org.hyperledger.besu.plugin.services.metrics.MetricCategoryRegistry; + +import java.util.ArrayList; +import java.util.List; + +public class MetricCategoryRegistryImpl implements MetricCategoryRegistry { + + private final List metricCategories = new ArrayList<>(); + + public List getMetricCategories() { + return metricCategories; + } + + @Override + public void addMetricCategory(final MetricCategory newMetricCategory) { + metricCategories.add(newMetricCategory); + } +} diff --git a/metrics/core/src/main/java/org/hyperledger/besu/metrics/prometheus/PrometheusMetricsSystem.java b/metrics/core/src/main/java/org/hyperledger/besu/metrics/prometheus/PrometheusMetricsSystem.java index 957a838a5d..a6f3ac13a4 100644 --- a/metrics/core/src/main/java/org/hyperledger/besu/metrics/prometheus/PrometheusMetricsSystem.java +++ b/metrics/core/src/main/java/org/hyperledger/besu/metrics/prometheus/PrometheusMetricsSystem.java @@ -156,7 +156,8 @@ public class PrometheusMetricsSystem implements ObservableMetricsSystem { } private boolean isCategoryEnabled(final MetricCategory category) { - return enabledCategories.contains(category); + return enabledCategories.stream() + .anyMatch(metricCategory -> metricCategory.getName().equals(category.getName())); } public void addCollector(final MetricCategory category, final Collector metric) { diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index c9c16a75a3..880d22cb10 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -56,7 +56,7 @@ Calculated : ${currentHash} tasks.register('checkAPIChanges', FileStateChecker) { description = "Checks that the API for the Plugin-API project does not change without deliberate thought" files = sourceSets.main.allJava.files - knownHash = 'azykDVSB2DOA/rgZyedO8Uwe1eGDGRCMUAZN4FMB3R4=' + knownHash = 'b8BCiNvy9vSYsTtS1NfszsVT0EMV8tiNc7igzXzTrak=' } check.dependsOn('checkAPIChanges') diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/metrics/PoAMetricsService.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/metrics/PoAMetricsService.java new file mode 100644 index 0000000000..96bfcc4501 --- /dev/null +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/metrics/PoAMetricsService.java @@ -0,0 +1,41 @@ +/* + * Copyright 2019 ConsenSys AG. + * + * 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.plugin.services.metrics; + +import org.hyperledger.besu.plugin.data.Address; +import org.hyperledger.besu.plugin.data.BlockHeader; + +import java.util.Collection; + +/** + * Provides relevant data for producing metrics on the status of a Proof of Authority (PoA) node. + */ +public interface PoAMetricsService { + + /** + * Retrieves the validators who have signed the latest block from the canonical chain. + * + * @return Identities of the validators who formed quorum on the latest block. + */ + Collection
getValidatorsForLatestBlock(); + + /** + * Retrieves the {@link Address} for the proposer of a block on the canonical chain. + * + * @param header The {@link BlockHeader} for which the proposer will be found. + * @return The identity of the proposer for the given block. + */ + Address getProposerOfBlock(final BlockHeader header); +}