Skip to content

Commit

Permalink
Bft validator provider (hyperledger#2570)
Browse files Browse the repository at this point in the history
Signed-off-by: Jason Frame <jasonwframe@gmail.com>
  • Loading branch information
jframe authored Jul 28, 2021
1 parent 1868d3c commit bdb9c1a
Show file tree
Hide file tree
Showing 103 changed files with 866 additions and 742 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@
import org.hyperledger.besu.consensus.clique.jsonrpc.CliqueJsonRpcMethods;
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.common.validator.blockbased.BlockValidatorProvider;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethods;
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
Expand Down Expand Up @@ -88,7 +86,7 @@ protected MiningCoordinator createMiningCoordinator(
miningParameters,
new CliqueBlockScheduler(
clock,
protocolContext.getConsensusState(CliqueContext.class).getVoteTallyCache(),
protocolContext.getConsensusState(CliqueContext.class).getValidatorProvider(),
localAddress,
secondsBetweenBlocks),
epochManager,
Expand Down Expand Up @@ -133,12 +131,8 @@ protected PluginServiceFactory createAdditionalPluginServices(final Blockchain b
protected CliqueContext createConsensusContext(
final Blockchain blockchain, final WorldStateArchive worldStateArchive) {
return new CliqueContext(
new VoteTallyCache(
blockchain,
new VoteTallyUpdater(epochManager, blockInterface),
epochManager,
blockInterface),
new VoteProposer(),
BlockValidatorProvider.nonForkingValidatorProvider(
blockchain, epochManager, blockInterface),
epochManager,
blockInterface);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@
import org.hyperledger.besu.config.BftConfigOptions;
import org.hyperledger.besu.config.BftFork;
import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.consensus.common.BftValidatorOverrides;
import org.hyperledger.besu.consensus.common.EpochManager;
import org.hyperledger.besu.consensus.common.ForkingVoteTallyCache;
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.common.bft.BftContext;
import org.hyperledger.besu.consensus.common.bft.BftEventQueue;
import org.hyperledger.besu.consensus.common.bft.BftExecutors;
Expand All @@ -43,6 +38,8 @@
import org.hyperledger.besu.consensus.common.bft.statemachine.BftEventHandler;
import org.hyperledger.besu.consensus.common.bft.statemachine.BftFinalState;
import org.hyperledger.besu.consensus.common.bft.statemachine.FutureMessageBuffer;
import org.hyperledger.besu.consensus.common.validator.ValidatorProvider;
import org.hyperledger.besu.consensus.common.validator.blockbased.BlockValidatorProvider;
import org.hyperledger.besu.consensus.ibft.IbftBlockHeaderValidationRulesetFactory;
import org.hyperledger.besu.consensus.ibft.IbftExtraDataCodec;
import org.hyperledger.besu.consensus.ibft.IbftGossip;
Expand Down Expand Up @@ -140,15 +137,15 @@ protected MiningCoordinator createMiningCoordinator(
bftConfig.getMiningBeneficiary().map(Address::fromHexString).orElse(localAddress),
bftExtraDataCodec().get());

// NOTE: peers should not be used for accessing the network as it does not enforce the
// "only send once" filter applied by the UniqueMessageMulticaster.
final VoteTallyCache voteTallyCache =
protocolContext.getConsensusState(BftContext.class).getVoteTallyCache();
final ValidatorProvider validatorProvider =
protocolContext.getConsensusState(BftContext.class).getValidatorProvider();

final ProposerSelector proposerSelector =
new ProposerSelector(blockchain, bftBlockInterface().get(), true, voteTallyCache);
new ProposerSelector(blockchain, bftBlockInterface().get(), true, validatorProvider);

peers = new ValidatorPeers(voteTallyCache, IbftSubProtocol.NAME);
// NOTE: peers should not be used for accessing the network as it does not enforce the
// "only send once" filter applied by the UniqueMessageMulticaster.
peers = new ValidatorPeers(validatorProvider, IbftSubProtocol.NAME);

final UniqueMessageMulticaster uniqueMessageMulticaster =
new UniqueMessageMulticaster(peers, bftConfig.getGossipedHistoryLimit());
Expand All @@ -157,7 +154,7 @@ protected MiningCoordinator createMiningCoordinator(

final BftFinalState finalState =
new BftFinalState(
voteTallyCache,
validatorProvider,
nodeKey,
Util.publicKeyToAddress(nodeKey.getPublicKey()),
proposerSelector,
Expand Down Expand Up @@ -254,17 +251,12 @@ protected BftContext createConsensusContext(
final BftConfigOptions ibftConfig = configOptions.getBftConfigOptions();
final EpochManager epochManager = new EpochManager(ibftConfig.getEpochLength());

final Map<Long, List<Address>> ibftValidatorForkMap =
final Map<Long, List<Address>> bftValidatorForkMap =
convertIbftForks(configOptions.getTransitions().getIbftForks());

return new BftContext(
new ForkingVoteTallyCache(
blockchain,
new VoteTallyUpdater(epochManager, bftBlockInterface().get()),
epochManager,
bftBlockInterface().get(),
new BftValidatorOverrides(ibftValidatorForkMap)),
new VoteProposer(),
BlockValidatorProvider.forkingValidatorProvider(
blockchain, epochManager, bftBlockInterface().get(), bftValidatorForkMap),
epochManager,
bftBlockInterface().get());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@
import org.hyperledger.besu.config.IbftLegacyConfigOptions;
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.common.validator.ValidatorProvider;
import org.hyperledger.besu.consensus.common.validator.blockbased.BlockValidatorProvider;
import org.hyperledger.besu.consensus.ibft.IbftLegacyContext;
import org.hyperledger.besu.consensus.ibftlegacy.IbftLegacyBlockInterface;
import org.hyperledger.besu.consensus.ibftlegacy.IbftProtocolSchedule;
Expand Down Expand Up @@ -86,16 +85,11 @@ protected IbftLegacyContext createConsensusContext(
final IbftLegacyConfigOptions ibftConfig =
genesisConfig.getConfigOptions(genesisConfigOverrides).getIbftLegacyConfigOptions();
final EpochManager epochManager = new EpochManager(ibftConfig.getEpochLength());
final VoteTallyCache voteTallyCache =
new VoteTallyCache(
blockchain,
new VoteTallyUpdater(epochManager, blockInterface),
epochManager,
blockInterface);
final ValidatorProvider validatorProvider =
BlockValidatorProvider.nonForkingValidatorProvider(
blockchain, epochManager, blockInterface);

final VoteProposer voteProposer = new VoteProposer();

return new IbftLegacyContext(voteTallyCache, voteProposer, epochManager, blockInterface);
return new IbftLegacyContext(validatorProvider, epochManager, blockInterface);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@
import org.hyperledger.besu.config.BftConfigOptions;
import org.hyperledger.besu.config.BftFork;
import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.consensus.common.BftValidatorOverrides;
import org.hyperledger.besu.consensus.common.EpochManager;
import org.hyperledger.besu.consensus.common.ForkingVoteTallyCache;
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.common.bft.BftContext;
import org.hyperledger.besu.consensus.common.bft.BftEventQueue;
import org.hyperledger.besu.consensus.common.bft.BftExecutors;
Expand All @@ -43,6 +38,8 @@
import org.hyperledger.besu.consensus.common.bft.statemachine.BftEventHandler;
import org.hyperledger.besu.consensus.common.bft.statemachine.BftFinalState;
import org.hyperledger.besu.consensus.common.bft.statemachine.FutureMessageBuffer;
import org.hyperledger.besu.consensus.common.validator.ValidatorProvider;
import org.hyperledger.besu.consensus.common.validator.blockbased.BlockValidatorProvider;
import org.hyperledger.besu.consensus.qbft.QbftBlockHeaderValidationRulesetFactory;
import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec;
import org.hyperledger.besu.consensus.qbft.QbftGossip;
Expand Down Expand Up @@ -143,15 +140,15 @@ protected MiningCoordinator createMiningCoordinator(
bftConfig.getMiningBeneficiary().map(Address::fromHexString).orElse(localAddress),
bftExtraDataCodec().get());

final VoteTallyCache voteTallyCache =
protocolContext.getConsensusState(BftContext.class).getVoteTallyCache();
final ValidatorProvider validatorProvider =
protocolContext.getConsensusState(BftContext.class).getValidatorProvider();

final ProposerSelector proposerSelector =
new ProposerSelector(blockchain, bftBlockInterface().get(), true, voteTallyCache);
new ProposerSelector(blockchain, bftBlockInterface().get(), true, validatorProvider);

// NOTE: peers should not be used for accessing the network as it does not enforce the
// "only send once" filter applied by the UniqueMessageMulticaster.
peers = new ValidatorPeers(voteTallyCache, Istanbul100SubProtocol.NAME);
peers = new ValidatorPeers(validatorProvider, Istanbul100SubProtocol.NAME);

final UniqueMessageMulticaster uniqueMessageMulticaster =
new UniqueMessageMulticaster(peers, bftConfig.getGossipedHistoryLimit());
Expand All @@ -160,7 +157,7 @@ protected MiningCoordinator createMiningCoordinator(

final BftFinalState finalState =
new BftFinalState(
voteTallyCache,
validatorProvider,
nodeKey,
Util.publicKeyToAddress(nodeKey.getPublicKey()),
proposerSelector,
Expand Down Expand Up @@ -261,13 +258,8 @@ protected BftContext createConsensusContext(
convertBftForks(configOptions.getTransitions().getQbftForks());

return new BftContext(
new ForkingVoteTallyCache(
blockchain,
new VoteTallyUpdater(epochManager, bftBlockInterface().get()),
epochManager,
bftBlockInterface().get(),
new BftValidatorOverrides(bftValidatorForkMap)),
new VoteProposer(),
BlockValidatorProvider.forkingValidatorProvider(
blockchain, epochManager, bftBlockInterface().get(), bftValidatorForkMap),
epochManager,
bftBlockInterface().get());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
package org.hyperledger.besu.consensus.clique;

import org.hyperledger.besu.consensus.common.BlockInterface;
import org.hyperledger.besu.consensus.common.ValidatorVote;
import org.hyperledger.besu.consensus.common.VoteType;
import org.hyperledger.besu.consensus.common.validator.ValidatorVote;
import org.hyperledger.besu.consensus.common.validator.VoteType;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,29 @@
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;
import org.hyperledger.besu.consensus.common.validator.ValidatorProvider;

/**
* Holds the data which lives "in parallel" with the importation of blocks etc. when using the
* Clique consensus mechanism.
*/
public class CliqueContext implements PoaContext {

private final VoteTallyCache voteTallyCache;
private final VoteProposer voteProposer;
private final ValidatorProvider validatorProvider;
private final EpochManager epochManager;
private final BlockInterface blockInterface;

public CliqueContext(
final VoteTallyCache voteTallyCache,
final VoteProposer voteProposer,
final ValidatorProvider validatorProvider,
final EpochManager epochManager,
final BlockInterface blockInterface) {
this.voteTallyCache = voteTallyCache;
this.voteProposer = voteProposer;
this.validatorProvider = validatorProvider;
this.epochManager = epochManager;
this.blockInterface = blockInterface;
}

public VoteTallyCache getVoteTallyCache() {
return voteTallyCache;
}

public VoteProposer getVoteProposer() {
return voteProposer;
public ValidatorProvider getValidatorProvider() {
return validatorProvider;
}

public EpochManager getEpochManager() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public BigInteger nextDifficulty(

final Address nextProposer =
CliqueHelpers.getProposerForBlockAfter(
parent, context.getConsensusState(CliqueContext.class).getVoteTallyCache());
parent, context.getConsensusState(CliqueContext.class).getValidatorProvider());
return nextProposer.equals(localAddress) ? IN_TURN_DIFFICULTY : OUT_OF_TURN_DIFFICULTY;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
package org.hyperledger.besu.consensus.clique;

import org.hyperledger.besu.consensus.clique.blockcreation.CliqueProposerSelector;
import org.hyperledger.besu.consensus.common.ValidatorProvider;
import org.hyperledger.besu.consensus.common.VoteTally;
import org.hyperledger.besu.consensus.common.VoteTallyCache;
import org.hyperledger.besu.consensus.common.validator.ValidatorProvider;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;

import java.util.Collection;

public class CliqueHelpers {

public static Address getProposerOfBlock(final BlockHeader header) {
Expand All @@ -31,34 +31,32 @@ public static Address getProposerOfBlock(final BlockHeader header) {
}

public static Address getProposerForBlockAfter(
final BlockHeader parent, final VoteTallyCache voteTallyCache) {
final CliqueProposerSelector proposerSelector = new CliqueProposerSelector(voteTallyCache);
final BlockHeader parent, final ValidatorProvider validatorProvider) {
final CliqueProposerSelector proposerSelector = new CliqueProposerSelector(validatorProvider);
return proposerSelector.selectProposerForNextBlock(parent);
}

public static boolean isSigner(
final Address candidate, final ProtocolContext protocolContext, final BlockHeader parent) {
final VoteTally validatorProvider =
final Collection<Address> validators =
protocolContext
.getConsensusState(CliqueContext.class)
.getVoteTallyCache()
.getVoteTallyAfterBlock(parent);
return validatorProvider.getValidators().contains(candidate);
.getValidatorProvider()
.getValidatorsAfterBlock(parent);
return validators.contains(candidate);
}

public static boolean addressIsAllowedToProduceNextBlock(
final Address candidate, final ProtocolContext protocolContext, final BlockHeader parent) {
final VoteTally validatorProvider =
protocolContext
.getConsensusState(CliqueContext.class)
.getVoteTallyCache()
.getVoteTallyAfterBlock(parent);
final ValidatorProvider validatorProvider =
protocolContext.getConsensusState(CliqueContext.class).getValidatorProvider();

if (!isSigner(candidate, protocolContext, parent)) {
return false;
}

final int minimumUnsignedPastBlocks = minimumBlocksSincePreviousSigning(validatorProvider);
final int minimumUnsignedPastBlocks =
minimumBlocksSincePreviousSigning(parent, validatorProvider);

final Blockchain blockchain = protocolContext.getBlockchain();
int unsignedBlockCount = 0;
Expand All @@ -85,8 +83,9 @@ public static boolean addressIsAllowedToProduceNextBlock(
return true;
}

private static int minimumBlocksSincePreviousSigning(final ValidatorProvider validatorProvider) {
final int validatorCount = validatorProvider.getValidators().size();
private static int minimumBlocksSincePreviousSigning(
final BlockHeader parent, final ValidatorProvider validatorProvider) {
final int validatorCount = validatorProvider.getValidatorsAfterBlock(parent).size();
// The number of contiguous blocks in which a signer may only sign 1 (as taken from clique spec)
final int signerLimit = (validatorCount / 2) + 1;
return signerLimit - 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public CliqueMiningTracker(final Address localAddress, final ProtocolContext pro
public boolean isProposerAfter(final BlockHeader header) {
final Address nextProposer =
CliqueHelpers.getProposerForBlockAfter(
header, protocolContext.getConsensusState(CliqueContext.class).getVoteTallyCache());
header, protocolContext.getConsensusState(CliqueContext.class).getValidatorProvider());
return localAddress.equals(nextProposer);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
*/
package org.hyperledger.besu.consensus.clique.blockcreation;

import static com.google.common.base.Preconditions.checkState;

import org.hyperledger.besu.consensus.clique.CliqueBlockHashing;
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.common.EpochManager;
import org.hyperledger.besu.consensus.common.ValidatorVote;
import org.hyperledger.besu.consensus.common.VoteTally;
import org.hyperledger.besu.consensus.common.validator.ValidatorVote;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.blockcreation.AbstractBlockCreator;
Expand Down Expand Up @@ -106,11 +107,14 @@ private Optional<ValidatorVote> determineCliqueVote(
return Optional.empty();
} else {
final CliqueContext cliqueContext = protocolContext.getConsensusState(CliqueContext.class);
final VoteTally voteTally =
cliqueContext.getVoteTallyCache().getVoteTallyAfterBlock(parentHeader);
checkState(
cliqueContext.getValidatorProvider().getVoteProvider().isPresent(),
"Clique requires a vote provider");
return cliqueContext
.getVoteProposer()
.getVote(Util.publicKeyToAddress(nodeKey.getPublicKey()), voteTally);
.getValidatorProvider()
.getVoteProvider()
.get()
.getVoteAfterBlock(parentHeader, Util.publicKeyToAddress(nodeKey.getPublicKey()));
}
}

Expand Down
Loading

0 comments on commit bdb9c1a

Please sign in to comment.