[BESU-179] getSignerMetrics doesn't return missing signers (#343)

* fix signer metrics add missing validator

* fix end block parameter issue

Signed-off-by: Karim TAAM <karim.t2am@gmail.com>
pull/346/head
Karim T 5 years ago committed by GitHub
parent f7db9d0ee4
commit b802fa75ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      besu/src/main/java/org/hyperledger/besu/controller/IbftBesuControllerBuilder.java
  2. 2
      besu/src/main/java/org/hyperledger/besu/controller/IbftLegacyBesuControllerBuilder.java
  3. 8
      consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/jsonrpc/CliqueJsonRpcMethods.java
  4. 7
      consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/jsonrpc/methods/CliqueGetSignerMetrics.java
  5. 22
      consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/jsonrpc/methods/CliqueGetSignerMetricsTest.java
  6. 19
      consensus/common/src/main/java/org/hyperledger/besu/consensus/common/jsonrpc/AbstractGetSignerMetricsMethod.java
  7. 2
      consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java
  8. 8
      consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/IbftContext.java
  9. 18
      consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/jsonrpc/IbftJsonRpcMethods.java
  10. 7
      consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/jsonrpc/methods/IbftGetSignerMetrics.java
  11. 19
      consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/jsonrpc/methods/IbftGetSignerMetricsTest.java

@ -243,6 +243,7 @@ public class IbftBesuControllerBuilder extends BesuControllerBuilder<IbftContext
new IbftBlockInterface(),
new IbftValidatorOverrides(ibftValidatorForkMap)),
new VoteProposer(),
epochManager,
blockInterface);
}

@ -89,7 +89,7 @@ public class IbftLegacyBesuControllerBuilder extends BesuControllerBuilder<IbftC
blockInterface);
final VoteProposer voteProposer = new VoteProposer();
return new IbftContext(voteTallyCache, voteProposer, blockInterface);
return new IbftContext(voteTallyCache, voteProposer, epochManager, blockInterface);
}
@Override

@ -65,15 +65,15 @@ public class CliqueJsonRpcMethods extends ApiGroupJsonRpcMethods {
new Propose(voteProposer),
new Discard(voteProposer),
new CliqueProposals(voteProposer),
new CliqueGetSignerMetrics(new CliqueBlockInterface(), blockchainQueries));
new CliqueGetSignerMetrics(voteTallyCache, new CliqueBlockInterface(), blockchainQueries));
}
private VoteTallyCache createVoteTallyCache(
final ProtocolContext<CliqueContext> context, final MutableBlockchain blockchain) {
final EpochManager epochManager = context.getConsensusState().getEpochManager();
final CliqueBlockInterface cliqueBlockInterface = new CliqueBlockInterface();
final VoteTallyUpdater voteTallyUpdater =
new VoteTallyUpdater(epochManager, new CliqueBlockInterface());
return new VoteTallyCache(
blockchain, voteTallyUpdater, epochManager, new CliqueBlockInterface());
new VoteTallyUpdater(epochManager, cliqueBlockInterface);
return new VoteTallyCache(blockchain, voteTallyUpdater, epochManager, cliqueBlockInterface);
}
}

@ -15,6 +15,7 @@
package org.hyperledger.besu.consensus.clique.jsonrpc.methods;
import org.hyperledger.besu.consensus.common.BlockInterface;
import org.hyperledger.besu.consensus.common.VoteTallyCache;
import org.hyperledger.besu.consensus.common.jsonrpc.AbstractGetSignerMetricsMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
@ -24,8 +25,10 @@ public class CliqueGetSignerMetrics extends AbstractGetSignerMetricsMethod
implements JsonRpcMethod {
public CliqueGetSignerMetrics(
final BlockInterface blockInterface, final BlockchainQueries blockchainQueries) {
super(blockInterface, blockchainQueries);
final VoteTallyCache voteTallyCache,
final BlockInterface blockInterface,
final BlockchainQueries blockchainQueries) {
super(voteTallyCache, blockInterface, blockchainQueries);
}
@Override

@ -22,6 +22,8 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.consensus.common.BlockInterface;
import org.hyperledger.besu.consensus.common.VoteTally;
import org.hyperledger.besu.consensus.common.VoteTallyCache;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters;
@ -33,6 +35,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
@ -46,13 +49,14 @@ import org.junit.rules.ExpectedException;
public class CliqueGetSignerMetricsTest {
private static final Address[] VALIDATORS = {
Address.fromHexString("0x1"), Address.fromHexString("0x2"), Address.fromHexString("0x3"),
Address.fromHexString("0x1"), Address.fromHexString("0x2"), Address.fromHexString("0x3")
};
private final String CLIQUE_METHOD = "clique_getSignerMetrics";
private final String JSON_RPC_VERSION = "2.0";
private CliqueGetSignerMetrics method;
private VoteTallyCache voteTallyCache;
private BlockchainQueries blockchainQueries;
private BlockInterface blockInterface;
@ -60,9 +64,10 @@ public class CliqueGetSignerMetricsTest {
@Before
public void setup() {
voteTallyCache = mock(VoteTallyCache.class);
blockchainQueries = mock(BlockchainQueries.class);
blockInterface = mock(BlockInterface.class);
method = new CliqueGetSignerMetrics(blockInterface, blockchainQueries);
method = new CliqueGetSignerMetrics(voteTallyCache, blockInterface, blockchainQueries);
}
@Test
@ -104,6 +109,8 @@ public class CliqueGetSignerMetricsTest {
LongStream.range(startBlock, endBlock)
.forEach(value -> signerMetricResultList.add(generateBlock(value)));
signerMetricResultList.add(new SignerMetricResult(VALIDATORS[0])); // missing validator
final JsonRpcRequestContext request = requestWithParams();
final JsonRpcSuccessResponse response = (JsonRpcSuccessResponse) method.response(request);
@ -158,6 +165,8 @@ public class CliqueGetSignerMetricsTest {
LongStream.range(startBlock, headBlock)
.forEach(value -> signerMetricResultList.add(generateBlock(value)));
signerMetricResultList.add(new SignerMetricResult(VALIDATORS[2])); // missing validator
final JsonRpcRequestContext request = requestWithParams();
final JsonRpcSuccessResponse response = (JsonRpcSuccessResponse) method.response(request);
@ -183,6 +192,8 @@ public class CliqueGetSignerMetricsTest {
LongStream.range(startBlock, endBlock)
.forEach(value -> signerMetricResultList.add(generateBlock(value)));
signerMetricResultList.add(new SignerMetricResult(VALIDATORS[0])); // missing validator
final JsonRpcRequestContext request = requestWithParams(String.valueOf(startBlock), "latest");
final JsonRpcSuccessResponse response = (JsonRpcSuccessResponse) method.response(request);
@ -205,6 +216,8 @@ public class CliqueGetSignerMetricsTest {
LongStream.range(startBlock, endBlock)
.forEach(value -> signerMetricResultList.add(generateBlock(value)));
signerMetricResultList.add(new SignerMetricResult(VALIDATORS[0])); // missing validator
final JsonRpcRequestContext request = requestWithParams(String.valueOf(startBlock), "pending");
final JsonRpcSuccessResponse response = (JsonRpcSuccessResponse) method.response(request);
@ -222,6 +235,8 @@ public class CliqueGetSignerMetricsTest {
final List<SignerMetricResult> signerMetricResultList = new ArrayList<>();
when(blockchainQueries.headBlockNumber()).thenReturn(endBlock);
LongStream.range(startBlock, endBlock)
.forEach(value -> signerMetricResultList.add(generateBlock(value)));
@ -246,6 +261,9 @@ public class CliqueGetSignerMetricsTest {
when(blockchainQueries.getBlockHeaderByNumber(number)).thenReturn(Optional.of(header));
when(blockInterface.getProposerOfBlock(header)).thenReturn(proposerAddressBlock);
when(voteTallyCache.getVoteTallyAfterBlock(header))
.thenReturn(new VoteTally(Arrays.asList(VALIDATORS)));
final SignerMetricResult signerMetricResult = new SignerMetricResult(proposerAddressBlock);
signerMetricResult.incrementeNbBlock();
signerMetricResult.setLastProposedBlockNumber(number);

@ -15,6 +15,7 @@
package org.hyperledger.besu.consensus.common.jsonrpc;
import org.hyperledger.besu.consensus.common.BlockInterface;
import org.hyperledger.besu.consensus.common.VoteTallyCache;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
@ -36,11 +37,15 @@ public abstract class AbstractGetSignerMetricsMethod {
private static final long DEFAULT_RANGE_BLOCK = 100;
private final VoteTallyCache voteTallyCache;
private final BlockInterface blockInterface;
private final BlockchainQueries blockchainQueries;
public AbstractGetSignerMetricsMethod(
final BlockInterface blockInterface, final BlockchainQueries blockchainQueries) {
final VoteTallyCache voteTallyCache,
final BlockInterface blockInterface,
final BlockchainQueries blockchainQueries) {
this.voteTallyCache = voteTallyCache;
this.blockInterface = blockInterface;
this.blockchainQueries = blockchainQueries;
}
@ -83,12 +88,12 @@ public abstract class AbstractGetSignerMetricsMethod {
// Get All validators present in the last block of the range even
// if they didn't propose a block
if (currentIndex == lastBlockIndex) {
blockInterface
.validatorsInBlock(header)
voteTallyCache
.getVoteTallyAfterBlock(header)
.getValidators()
.forEach(
address ->
proposersMap.computeIfAbsent(
proposerAddress, SignerMetricResult::new));
proposersMap.computeIfAbsent(address, SignerMetricResult::new));
}
});
});
@ -104,9 +109,11 @@ public abstract class AbstractGetSignerMetricsMethod {
}
private long getEndBlockNumber(final Optional<BlockParameter> endBlockParameter) {
final long headBlockNumber = blockchainQueries.headBlockNumber();
return endBlockParameter
.map(this::resolveBlockNumber)
.orElseGet(blockchainQueries::headBlockNumber);
.filter(blockNumber -> blockNumber <= headBlockNumber)
.orElse(headBlockNumber);
}
private boolean isValidParameters(final long startBlock, final long endBlock) {

@ -296,7 +296,7 @@ public class TestContextBuilder {
new ProtocolContext<>(
blockChain,
worldStateArchive,
new IbftContext(voteTallyCache, voteProposer, blockInterface));
new IbftContext(voteTallyCache, voteProposer, epochManager, blockInterface));
final PendingTransactions pendingTransactions =
new PendingTransactions(

@ -15,6 +15,7 @@
package org.hyperledger.besu.consensus.ibft;
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;
@ -24,14 +25,17 @@ public class IbftContext implements PoaContext {
private final VoteTallyCache voteTallyCache;
private final VoteProposer voteProposer;
private final EpochManager epochManager;
private final BlockInterface blockInterface;
public IbftContext(
final VoteTallyCache voteTallyCache,
final VoteProposer voteProposer,
final EpochManager epochManager,
final BlockInterface blockInterface) {
this.voteTallyCache = voteTallyCache;
this.voteProposer = voteProposer;
this.epochManager = epochManager;
this.blockInterface = blockInterface;
}
@ -43,6 +47,10 @@ public class IbftContext implements PoaContext {
return voteProposer;
}
public EpochManager getEpochManager() {
return epochManager;
}
@Override
public BlockInterface getBlockInterface() {
return blockInterface;

@ -15,7 +15,10 @@
package org.hyperledger.besu.consensus.ibft.jsonrpc;
import org.hyperledger.besu.consensus.common.BlockInterface;
import org.hyperledger.besu.consensus.common.EpochManager;
import org.hyperledger.besu.consensus.common.VoteProposer;
import org.hyperledger.besu.consensus.common.VoteTallyCache;
import org.hyperledger.besu.consensus.common.VoteTallyUpdater;
import org.hyperledger.besu.consensus.ibft.IbftBlockInterface;
import org.hyperledger.besu.consensus.ibft.IbftContext;
import org.hyperledger.besu.consensus.ibft.jsonrpc.methods.IbftDiscardValidatorVote;
@ -29,6 +32,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.methods.ApiGroupJsonRpcMethods;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import java.util.Map;
@ -47,17 +51,29 @@ public class IbftJsonRpcMethods extends ApiGroupJsonRpcMethods {
@Override
protected Map<String, JsonRpcMethod> create() {
final MutableBlockchain mutableBlockchain = context.getBlockchain();
final BlockchainQueries blockchainQueries =
new BlockchainQueries(context.getBlockchain(), context.getWorldStateArchive());
final VoteProposer voteProposer = context.getConsensusState().getVoteProposer();
final BlockInterface blockInterface = new IbftBlockInterface();
final VoteTallyCache voteTallyCache = createVoteTallyCache(context, mutableBlockchain);
return mapOf(
new IbftProposeValidatorVote(voteProposer),
new IbftGetValidatorsByBlockNumber(blockchainQueries, blockInterface),
new IbftDiscardValidatorVote(voteProposer),
new IbftGetValidatorsByBlockHash(context.getBlockchain(), blockInterface),
new IbftGetSignerMetrics(blockInterface, blockchainQueries),
new IbftGetSignerMetrics(voteTallyCache, blockInterface, blockchainQueries),
new IbftGetPendingVotes(voteProposer));
}
private VoteTallyCache createVoteTallyCache(
final ProtocolContext<IbftContext> context, final MutableBlockchain blockchain) {
final EpochManager epochManager = context.getConsensusState().getEpochManager();
final IbftBlockInterface ibftBlockInterface = new IbftBlockInterface();
final VoteTallyUpdater voteTallyUpdater =
new VoteTallyUpdater(epochManager, ibftBlockInterface);
return new VoteTallyCache(blockchain, voteTallyUpdater, epochManager, ibftBlockInterface);
}
}

@ -15,6 +15,7 @@
package org.hyperledger.besu.consensus.ibft.jsonrpc.methods;
import org.hyperledger.besu.consensus.common.BlockInterface;
import org.hyperledger.besu.consensus.common.VoteTallyCache;
import org.hyperledger.besu.consensus.common.jsonrpc.AbstractGetSignerMetricsMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
@ -23,8 +24,10 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
public class IbftGetSignerMetrics extends AbstractGetSignerMetricsMethod implements JsonRpcMethod {
public IbftGetSignerMetrics(
final BlockInterface blockInterface, final BlockchainQueries blockchainQueries) {
super(blockInterface, blockchainQueries);
final VoteTallyCache voteTallyCache,
final BlockInterface blockInterface,
final BlockchainQueries blockchainQueries) {
super(voteTallyCache, blockInterface, blockchainQueries);
}
@Override

@ -22,6 +22,8 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.consensus.common.BlockInterface;
import org.hyperledger.besu.consensus.common.VoteTally;
import org.hyperledger.besu.consensus.common.VoteTallyCache;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters;
@ -33,6 +35,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
@ -53,6 +56,7 @@ public class IbftGetSignerMetricsTest {
private final String JSON_RPC_VERSION = "2.0";
private IbftGetSignerMetrics method;
private VoteTallyCache voteTallyCache;
private BlockchainQueries blockchainQueries;
private BlockInterface blockInterface;
@ -60,9 +64,10 @@ public class IbftGetSignerMetricsTest {
@Before
public void setup() {
voteTallyCache = mock(VoteTallyCache.class);
blockchainQueries = mock(BlockchainQueries.class);
blockInterface = mock(BlockInterface.class);
method = new IbftGetSignerMetrics(blockInterface, blockchainQueries);
method = new IbftGetSignerMetrics(voteTallyCache, blockInterface, blockchainQueries);
}
@Test
@ -104,6 +109,8 @@ public class IbftGetSignerMetricsTest {
LongStream.range(startBlock, endBlock)
.forEach(value -> signerMetricResultList.add(generateBlock(value)));
signerMetricResultList.add(new SignerMetricResult(VALIDATORS[0])); // missing validator
final JsonRpcRequestContext request = requestWithParams();
final JsonRpcSuccessResponse response = (JsonRpcSuccessResponse) method.response(request);
@ -158,6 +165,8 @@ public class IbftGetSignerMetricsTest {
LongStream.range(startBlock, headBlock)
.forEach(value -> signerMetricResultList.add(generateBlock(value)));
signerMetricResultList.add(new SignerMetricResult(VALIDATORS[2])); // missing validator
final JsonRpcRequestContext request = requestWithParams();
final JsonRpcSuccessResponse response = (JsonRpcSuccessResponse) method.response(request);
@ -183,6 +192,8 @@ public class IbftGetSignerMetricsTest {
LongStream.range(startBlock, endBlock)
.forEach(value -> signerMetricResultList.add(generateBlock(value)));
signerMetricResultList.add(new SignerMetricResult(VALIDATORS[0])); // missing validator
final JsonRpcRequestContext request = requestWithParams(String.valueOf(startBlock), "latest");
final JsonRpcSuccessResponse response = (JsonRpcSuccessResponse) method.response(request);
@ -205,6 +216,8 @@ public class IbftGetSignerMetricsTest {
LongStream.range(startBlock, endBlock)
.forEach(value -> signerMetricResultList.add(generateBlock(value)));
signerMetricResultList.add(new SignerMetricResult(VALIDATORS[0])); // missing validator
final JsonRpcRequestContext request = requestWithParams(String.valueOf(startBlock), "pending");
final JsonRpcSuccessResponse response = (JsonRpcSuccessResponse) method.response(request);
@ -222,6 +235,8 @@ public class IbftGetSignerMetricsTest {
final List<SignerMetricResult> signerMetricResultList = new ArrayList<>();
when(blockchainQueries.headBlockNumber()).thenReturn(endBlock);
LongStream.range(startBlock, endBlock)
.forEach(value -> signerMetricResultList.add(generateBlock(value)));
@ -244,6 +259,8 @@ public class IbftGetSignerMetricsTest {
when(blockchainQueries.getBlockHeaderByNumber(number)).thenReturn(Optional.of(header));
when(blockInterface.getProposerOfBlock(header)).thenReturn(proposerAddressBlock);
when(voteTallyCache.getVoteTallyAfterBlock(header))
.thenReturn(new VoteTally(Arrays.asList(VALIDATORS)));
final SignerMetricResult signerMetricResult = new SignerMetricResult(proposerAddressBlock);
signerMetricResult.incrementeNbBlock();

Loading…
Cancel
Save