Ibft validates block on proposal reception (#583)

Previously, IBFT only validated the header of the block on reception
of a proposal. However in order to minimise the risk of a "bad block"
being detected after a PreparedCertificate being created, it has been
decided to validate the whole block (i.e. exercise the transactions,
process the block and ensure hashes etc line up with the header).

There is still some (minor) risk of a failed block import, however
it is substantially reduced.

Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
tmohay 6 years ago committed by GitHub
parent 84e39953e0
commit 9334e3085f
  1. 8
      consensus/ibft/src/integration-test/java/tech/pegasys/pantheon/consensus/ibft/support/TestContextFactory.java
  2. 29
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHeaderValidationRulesetFactory.java
  3. 5
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/headervalidationrules/IbftCommitSealsValidationRule.java
  4. 9
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftFinalState.java
  5. 6
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftRoundFactory.java
  6. 22
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/validation/MessageValidator.java
  7. 14
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/validation/MessageValidatorFactory.java
  8. 5
      consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/IbftBlockCreatorTest.java
  9. 16
      consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/statemachine/RoundChangeManagerTest.java
  10. 113
      consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/validation/MessageValidatorTest.java
  11. 9
      pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonController.java

@ -25,7 +25,6 @@ import tech.pegasys.pantheon.consensus.common.VoteTally;
import tech.pegasys.pantheon.consensus.common.VoteTallyUpdater; import tech.pegasys.pantheon.consensus.common.VoteTallyUpdater;
import tech.pegasys.pantheon.consensus.ibft.BlockTimer; import tech.pegasys.pantheon.consensus.ibft.BlockTimer;
import tech.pegasys.pantheon.consensus.ibft.IbftBlockHashing; import tech.pegasys.pantheon.consensus.ibft.IbftBlockHashing;
import tech.pegasys.pantheon.consensus.ibft.IbftBlockHeaderValidationRulesetFactory;
import tech.pegasys.pantheon.consensus.ibft.IbftBlockInterface; import tech.pegasys.pantheon.consensus.ibft.IbftBlockInterface;
import tech.pegasys.pantheon.consensus.ibft.IbftContext; import tech.pegasys.pantheon.consensus.ibft.IbftContext;
import tech.pegasys.pantheon.consensus.ibft.IbftEventQueue; import tech.pegasys.pantheon.consensus.ibft.IbftEventQueue;
@ -58,7 +57,6 @@ import tech.pegasys.pantheon.ethereum.core.PendingTransactions;
import tech.pegasys.pantheon.ethereum.core.Util; import tech.pegasys.pantheon.ethereum.core.Util;
import tech.pegasys.pantheon.ethereum.core.Wei; import tech.pegasys.pantheon.ethereum.core.Wei;
import tech.pegasys.pantheon.ethereum.db.WorldStateArchive; import tech.pegasys.pantheon.ethereum.db.WorldStateArchive;
import tech.pegasys.pantheon.ethereum.mainnet.BlockHeaderValidator;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.util.Subscribers; import tech.pegasys.pantheon.util.Subscribers;
@ -233,9 +231,6 @@ public class TestContextFactory {
final ProposerSelector proposerSelector = final ProposerSelector proposerSelector =
new ProposerSelector(blockChain, voteTally, blockInterface, true); new ProposerSelector(blockChain, voteTally, blockInterface, true);
final BlockHeaderValidator<IbftContext> blockHeaderValidator =
IbftBlockHeaderValidationRulesetFactory.ibftProposedBlockValidator(BLOCK_TIMER_SEC);
final IbftFinalState finalState = final IbftFinalState finalState =
new IbftFinalState( new IbftFinalState(
voteTally, voteTally,
@ -252,11 +247,10 @@ public class TestContextFactory {
Clock.systemUTC()), Clock.systemUTC()),
blockCreatorFactory, blockCreatorFactory,
new MessageFactory(nodeKeys), new MessageFactory(nodeKeys),
blockHeaderValidator,
clock); clock);
final MessageValidatorFactory messageValidatorFactory = final MessageValidatorFactory messageValidatorFactory =
new MessageValidatorFactory(proposerSelector, blockHeaderValidator, protocolContext); new MessageValidatorFactory(proposerSelector, protocolSchedule, protocolContext);
// Disable Gossiping for integration tests. // Disable Gossiping for integration tests.
final IbftGossip gossiper = mock(IbftGossip.class); final IbftGossip gossiper = mock(IbftGossip.class);

@ -37,26 +37,7 @@ public class IbftBlockHeaderValidationRulesetFactory {
*/ */
public static BlockHeaderValidator<IbftContext> ibftBlockHeaderValidator( public static BlockHeaderValidator<IbftContext> ibftBlockHeaderValidator(
final long secondsBetweenBlocks) { final long secondsBetweenBlocks) {
return createValidator(secondsBetweenBlocks, true); return new BlockHeaderValidator.Builder<IbftContext>()
}
/**
* Produces a BlockHeaderValidator configured for assessing IBFT proposed blocks (i.e. blocks
* which need to be vetted by the validators, and do not contain commit seals).
*
* @param secondsBetweenBlocks the minimum number of seconds which must elapse between blocks.
* @return BlockHeaderValidator configured for assessing ibft block headers
*/
public static BlockHeaderValidator<IbftContext> ibftProposedBlockValidator(
final long secondsBetweenBlocks) {
return createValidator(secondsBetweenBlocks, false);
}
private static BlockHeaderValidator<IbftContext> createValidator(
final long secondsBetweenBlocks, final boolean validateCommitSeals) {
final BlockHeaderValidator.Builder<IbftContext> builder = new BlockHeaderValidator.Builder<>();
builder
.addRule(new AncestryValidationRule()) .addRule(new AncestryValidationRule())
.addRule(new GasUsageValidationRule()) .addRule(new GasUsageValidationRule())
.addRule(new GasLimitRangeAndDeltaValidationRule(5000, 0x7fffffffffffffffL)) .addRule(new GasLimitRangeAndDeltaValidationRule(5000, 0x7fffffffffffffffL))
@ -73,10 +54,8 @@ public class IbftBlockHeaderValidationRulesetFactory {
"Difficulty", BlockHeader::getDifficulty, UInt256.ONE)) "Difficulty", BlockHeader::getDifficulty, UInt256.ONE))
.addRule(new ConstantFieldValidationRule<>("Nonce", BlockHeader::getNonce, 0L)) .addRule(new ConstantFieldValidationRule<>("Nonce", BlockHeader::getNonce, 0L))
.addRule(new IbftValidatorsValidationRule()) .addRule(new IbftValidatorsValidationRule())
.addRule(new IbftCoinbaseValidationRule()); .addRule(new IbftCoinbaseValidationRule())
if (validateCommitSeals) { .addRule(new IbftCommitSealsValidationRule())
builder.addRule(new IbftCommitSealsValidationRule()); .build();
}
return builder.build();
} }
} }

@ -73,4 +73,9 @@ public class IbftCommitSealsValidationRule
return true; return true;
} }
@Override
public boolean includeInLightValidation() {
return false;
}
} }

@ -17,7 +17,6 @@ import static tech.pegasys.pantheon.consensus.ibft.IbftHelpers.calculateRequired
import tech.pegasys.pantheon.consensus.common.ValidatorProvider; import tech.pegasys.pantheon.consensus.common.ValidatorProvider;
import tech.pegasys.pantheon.consensus.ibft.BlockTimer; import tech.pegasys.pantheon.consensus.ibft.BlockTimer;
import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier; import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibft.IbftContext;
import tech.pegasys.pantheon.consensus.ibft.RoundTimer; import tech.pegasys.pantheon.consensus.ibft.RoundTimer;
import tech.pegasys.pantheon.consensus.ibft.blockcreation.IbftBlockCreatorFactory; import tech.pegasys.pantheon.consensus.ibft.blockcreation.IbftBlockCreatorFactory;
import tech.pegasys.pantheon.consensus.ibft.blockcreation.ProposerSelector; import tech.pegasys.pantheon.consensus.ibft.blockcreation.ProposerSelector;
@ -26,7 +25,6 @@ import tech.pegasys.pantheon.consensus.ibft.network.ValidatorMulticaster;
import tech.pegasys.pantheon.consensus.ibft.payload.MessageFactory; import tech.pegasys.pantheon.consensus.ibft.payload.MessageFactory;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.mainnet.BlockHeaderValidator;
import java.time.Clock; import java.time.Clock;
import java.util.Collection; import java.util.Collection;
@ -42,7 +40,6 @@ public class IbftFinalState {
private final BlockTimer blockTimer; private final BlockTimer blockTimer;
private final IbftBlockCreatorFactory blockCreatorFactory; private final IbftBlockCreatorFactory blockCreatorFactory;
private final MessageFactory messageFactory; private final MessageFactory messageFactory;
private final BlockHeaderValidator<IbftContext> ibftContextBlockHeaderValidator;
private final IbftMessageTransmitter messageTransmitter; private final IbftMessageTransmitter messageTransmitter;
private final Clock clock; private final Clock clock;
@ -56,7 +53,6 @@ public class IbftFinalState {
final BlockTimer blockTimer, final BlockTimer blockTimer,
final IbftBlockCreatorFactory blockCreatorFactory, final IbftBlockCreatorFactory blockCreatorFactory,
final MessageFactory messageFactory, final MessageFactory messageFactory,
final BlockHeaderValidator<IbftContext> ibftContextBlockHeaderValidator,
final Clock clock) { final Clock clock) {
this.validatorProvider = validatorProvider; this.validatorProvider = validatorProvider;
this.nodeKeys = nodeKeys; this.nodeKeys = nodeKeys;
@ -67,7 +63,6 @@ public class IbftFinalState {
this.blockTimer = blockTimer; this.blockTimer = blockTimer;
this.blockCreatorFactory = blockCreatorFactory; this.blockCreatorFactory = blockCreatorFactory;
this.messageFactory = messageFactory; this.messageFactory = messageFactory;
this.ibftContextBlockHeaderValidator = ibftContextBlockHeaderValidator;
this.clock = clock; this.clock = clock;
this.messageTransmitter = new IbftMessageTransmitter(messageFactory, validatorMulticaster); this.messageTransmitter = new IbftMessageTransmitter(messageFactory, validatorMulticaster);
} }
@ -116,10 +111,6 @@ public class IbftFinalState {
return proposerSelector.selectProposerForRound(roundIdentifier); return proposerSelector.selectProposerForRound(roundIdentifier);
} }
public BlockHeaderValidator<IbftContext> getBlockHeaderValidator() {
return ibftContextBlockHeaderValidator;
}
public IbftMessageTransmitter getTransmitter() { public IbftMessageTransmitter getTransmitter() {
return messageTransmitter; return messageTransmitter;
} }

@ -17,6 +17,7 @@ import tech.pegasys.pantheon.consensus.ibft.IbftContext;
import tech.pegasys.pantheon.consensus.ibft.blockcreation.IbftBlockCreator; import tech.pegasys.pantheon.consensus.ibft.blockcreation.IbftBlockCreator;
import tech.pegasys.pantheon.consensus.ibft.blockcreation.IbftBlockCreatorFactory; import tech.pegasys.pantheon.consensus.ibft.blockcreation.IbftBlockCreatorFactory;
import tech.pegasys.pantheon.consensus.ibft.validation.MessageValidator; import tech.pegasys.pantheon.consensus.ibft.validation.MessageValidator;
import tech.pegasys.pantheon.ethereum.BlockValidator;
import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.chain.MinedBlockObserver; import tech.pegasys.pantheon.ethereum.chain.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.BlockHeader;
@ -47,6 +48,9 @@ public class IbftRoundFactory {
final ConsensusRoundIdentifier roundIdentifier = final ConsensusRoundIdentifier roundIdentifier =
new ConsensusRoundIdentifier(nextBlockHeight, round); new ConsensusRoundIdentifier(nextBlockHeight, round);
BlockValidator<IbftContext> blockValidator =
protocolSchedule.getByBlockNumber(nextBlockHeight).getBlockValidator();
final RoundState roundState = final RoundState roundState =
new RoundState( new RoundState(
roundIdentifier, roundIdentifier,
@ -55,7 +59,7 @@ public class IbftRoundFactory {
finalState.getValidators(), finalState.getValidators(),
finalState.getProposerForRound(roundIdentifier), finalState.getProposerForRound(roundIdentifier),
roundIdentifier, roundIdentifier,
finalState.getBlockHeaderValidator(), blockValidator,
protocolContext, protocolContext,
parentHeader)); parentHeader));

@ -12,8 +12,6 @@
*/ */
package tech.pegasys.pantheon.consensus.ibft.validation; package tech.pegasys.pantheon.consensus.ibft.validation;
import static tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode.FULL;
import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier; import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibft.IbftContext; import tech.pegasys.pantheon.consensus.ibft.IbftContext;
import tech.pegasys.pantheon.consensus.ibft.IbftExtraData; import tech.pegasys.pantheon.consensus.ibft.IbftExtraData;
@ -22,13 +20,15 @@ import tech.pegasys.pantheon.consensus.ibft.payload.Payload;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparePayload; import tech.pegasys.pantheon.consensus.ibft.payload.PreparePayload;
import tech.pegasys.pantheon.consensus.ibft.payload.ProposalPayload; import tech.pegasys.pantheon.consensus.ibft.payload.ProposalPayload;
import tech.pegasys.pantheon.consensus.ibft.payload.SignedData; import tech.pegasys.pantheon.consensus.ibft.payload.SignedData;
import tech.pegasys.pantheon.ethereum.BlockValidator;
import tech.pegasys.pantheon.ethereum.BlockValidator.BlockProcessingOutputs;
import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.Block; import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.Hash; import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.core.Util; import tech.pegasys.pantheon.ethereum.core.Util;
import tech.pegasys.pantheon.ethereum.mainnet.BlockHeaderValidator; import tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode;
import java.util.Collection; import java.util.Collection;
import java.util.Optional; import java.util.Optional;
@ -43,7 +43,7 @@ public class MessageValidator {
private final Collection<Address> validators; private final Collection<Address> validators;
private final Address expectedProposer; private final Address expectedProposer;
private final ConsensusRoundIdentifier roundIdentifier; private final ConsensusRoundIdentifier roundIdentifier;
private final BlockHeaderValidator<IbftContext> headerValidator; private final BlockValidator<IbftContext> blockValidator;
private final ProtocolContext<IbftContext> protocolContext; private final ProtocolContext<IbftContext> protocolContext;
private final BlockHeader parentHeader; private final BlockHeader parentHeader;
@ -53,13 +53,13 @@ public class MessageValidator {
final Collection<Address> validators, final Collection<Address> validators,
final Address expectedProposer, final Address expectedProposer,
final ConsensusRoundIdentifier roundIdentifier, final ConsensusRoundIdentifier roundIdentifier,
final BlockHeaderValidator<IbftContext> headerValidator, final BlockValidator<IbftContext> blockValidator,
final ProtocolContext<IbftContext> protocolContext, final ProtocolContext<IbftContext> protocolContext,
final BlockHeader parentHeader) { final BlockHeader parentHeader) {
this.validators = validators; this.validators = validators;
this.expectedProposer = expectedProposer; this.expectedProposer = expectedProposer;
this.roundIdentifier = roundIdentifier; this.roundIdentifier = roundIdentifier;
this.headerValidator = headerValidator; this.blockValidator = blockValidator;
this.protocolContext = protocolContext; this.protocolContext = protocolContext;
this.parentHeader = parentHeader; this.parentHeader = parentHeader;
} }
@ -97,9 +97,13 @@ public class MessageValidator {
} }
final Block proposedBlock = msg.getPayload().getBlock(); final Block proposedBlock = msg.getPayload().getBlock();
if (!headerValidator.validateHeader(
proposedBlock.getHeader(), parentHeader, protocolContext, FULL)) { final Optional<BlockProcessingOutputs> validationResult =
LOG.info("Invalid Proposal message, block did not pass header validation."); blockValidator.validateAndProcessBlock(
protocolContext, proposedBlock, HeaderValidationMode.LIGHT, HeaderValidationMode.FULL);
if (!validationResult.isPresent()) {
LOG.info("Invalid Proposal message, block did not pass validation.");
return false; return false;
} }

@ -18,35 +18,39 @@ import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibft.IbftContext; import tech.pegasys.pantheon.consensus.ibft.IbftContext;
import tech.pegasys.pantheon.consensus.ibft.IbftHelpers; import tech.pegasys.pantheon.consensus.ibft.IbftHelpers;
import tech.pegasys.pantheon.consensus.ibft.blockcreation.ProposerSelector; import tech.pegasys.pantheon.consensus.ibft.blockcreation.ProposerSelector;
import tech.pegasys.pantheon.ethereum.BlockValidator;
import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.mainnet.BlockHeaderValidator; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import java.util.Collection; import java.util.Collection;
public class MessageValidatorFactory { public class MessageValidatorFactory {
private final ProposerSelector proposerSelector; private final ProposerSelector proposerSelector;
private final BlockHeaderValidator<IbftContext> blockHeaderValidator;
private final ProtocolContext<IbftContext> protocolContext; private final ProtocolContext<IbftContext> protocolContext;
private final ProtocolSchedule<IbftContext> protocolSchedule;
public MessageValidatorFactory( public MessageValidatorFactory(
final ProposerSelector proposerSelector, final ProposerSelector proposerSelector,
final BlockHeaderValidator<IbftContext> blockHeaderValidator, final ProtocolSchedule<IbftContext> protocolSchedule,
final ProtocolContext<IbftContext> protocolContext) { final ProtocolContext<IbftContext> protocolContext) {
this.proposerSelector = proposerSelector; this.proposerSelector = proposerSelector;
this.blockHeaderValidator = blockHeaderValidator; this.protocolSchedule = protocolSchedule;
this.protocolContext = protocolContext; this.protocolContext = protocolContext;
} }
public MessageValidator createMessageValidator( public MessageValidator createMessageValidator(
final ConsensusRoundIdentifier roundIdentifier, final BlockHeader parentHeader) { final ConsensusRoundIdentifier roundIdentifier, final BlockHeader parentHeader) {
final BlockValidator<IbftContext> blockValidator =
protocolSchedule.getByBlockNumber(roundIdentifier.getSequenceNumber()).getBlockValidator();
return new MessageValidator( return new MessageValidator(
protocolContext.getConsensusState().getVoteTally().getValidators(), protocolContext.getConsensusState().getVoteTally().getValidators(),
proposerSelector.selectProposerForRound(roundIdentifier), proposerSelector.selectProposerForRound(roundIdentifier),
roundIdentifier, roundIdentifier,
blockHeaderValidator, blockValidator,
protocolContext, protocolContext,
parentHeader); parentHeader);
} }

@ -103,11 +103,12 @@ public class IbftBlockCreatorTest {
final Block block = blockCreator.createBlock(Instant.now().getEpochSecond()); final Block block = blockCreator.createBlock(Instant.now().getEpochSecond());
final BlockHeaderValidator<IbftContext> rules = final BlockHeaderValidator<IbftContext> rules =
IbftBlockHeaderValidationRulesetFactory.ibftProposedBlockValidator(0); IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(0);
// NOTE: The header will not contain commit seals, so can only do light validation on header.
final boolean validationResult = final boolean validationResult =
rules.validateHeader( rules.validateHeader(
block.getHeader(), parentHeader, protContext, HeaderValidationMode.FULL); block.getHeader(), parentHeader, protContext, HeaderValidationMode.LIGHT);
assertThat(validationResult).isTrue(); assertThat(validationResult).isTrue();

@ -30,6 +30,8 @@ import tech.pegasys.pantheon.consensus.ibft.payload.SignedData;
import tech.pegasys.pantheon.consensus.ibft.validation.MessageValidator; import tech.pegasys.pantheon.consensus.ibft.validation.MessageValidator;
import tech.pegasys.pantheon.consensus.ibft.validation.RoundChangeMessageValidator; import tech.pegasys.pantheon.consensus.ibft.validation.RoundChangeMessageValidator;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.BlockValidator;
import tech.pegasys.pantheon.ethereum.BlockValidator.BlockProcessingOutputs;
import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.Address;
@ -37,7 +39,6 @@ import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.Util; import tech.pegasys.pantheon.ethereum.core.Util;
import tech.pegasys.pantheon.ethereum.db.WorldStateArchive; import tech.pegasys.pantheon.ethereum.db.WorldStateArchive;
import tech.pegasys.pantheon.ethereum.mainnet.BlockHeaderValidator;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -75,9 +76,10 @@ public class RoundChangeManagerTest {
mock(MutableBlockchain.class), mock(WorldStateArchive.class), mock(IbftContext.class)); mock(MutableBlockchain.class), mock(WorldStateArchive.class), mock(IbftContext.class));
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
BlockHeaderValidator<IbftContext> headerValidator = BlockValidator<IbftContext> blockValidator =
(BlockHeaderValidator<IbftContext>) mock(BlockHeaderValidator.class); (BlockValidator<IbftContext>) mock(BlockValidator.class);
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
.thenReturn(Optional.of(new BlockProcessingOutputs(null, null)));
BlockHeader parentHeader = mock(BlockHeader.class); BlockHeader parentHeader = mock(BlockHeader.class);
RoundChangeMessageValidator.MessageValidatorForHeightFactory messageValidatorFactory = RoundChangeMessageValidator.MessageValidatorForHeightFactory messageValidatorFactory =
@ -90,7 +92,7 @@ public class RoundChangeManagerTest {
validators, validators,
Util.publicKeyToAddress(proposerKey.getPublicKey()), Util.publicKeyToAddress(proposerKey.getPublicKey()),
ri1, ri1,
headerValidator, blockValidator,
protocolContext, protocolContext,
parentHeader)); parentHeader));
when(messageValidatorFactory.createAt(ri2)) when(messageValidatorFactory.createAt(ri2))
@ -100,7 +102,7 @@ public class RoundChangeManagerTest {
validators, validators,
Util.publicKeyToAddress(validator1Key.getPublicKey()), Util.publicKeyToAddress(validator1Key.getPublicKey()),
ri2, ri2,
headerValidator, blockValidator,
protocolContext, protocolContext,
parentHeader)); parentHeader));
when(messageValidatorFactory.createAt(ri3)) when(messageValidatorFactory.createAt(ri3))
@ -110,7 +112,7 @@ public class RoundChangeManagerTest {
validators, validators,
Util.publicKeyToAddress(validator2Key.getPublicKey()), Util.publicKeyToAddress(validator2Key.getPublicKey()),
ri3, ri3,
headerValidator, blockValidator,
protocolContext, protocolContext,
parentHeader)); parentHeader));

@ -12,6 +12,7 @@
*/ */
package tech.pegasys.pantheon.consensus.ibft.validation; package tech.pegasys.pantheon.consensus.ibft.validation;
import static java.util.Optional.empty;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@ -27,6 +28,8 @@ import tech.pegasys.pantheon.consensus.ibft.payload.ProposalPayload;
import tech.pegasys.pantheon.consensus.ibft.payload.SignedData; import tech.pegasys.pantheon.consensus.ibft.payload.SignedData;
import tech.pegasys.pantheon.crypto.SECP256K1; import tech.pegasys.pantheon.crypto.SECP256K1;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.BlockValidator;
import tech.pegasys.pantheon.ethereum.BlockValidator.BlockProcessingOutputs;
import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.Address;
@ -35,7 +38,6 @@ import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.Hash; import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.core.Util; import tech.pegasys.pantheon.ethereum.core.Util;
import tech.pegasys.pantheon.ethereum.db.WorldStateArchive; import tech.pegasys.pantheon.ethereum.db.WorldStateArchive;
import tech.pegasys.pantheon.ethereum.mainnet.BlockHeaderValidator;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.Collections; import java.util.Collections;
@ -61,7 +63,7 @@ public class MessageValidatorTest {
private final List<Address> validators = Lists.newArrayList(); private final List<Address> validators = Lists.newArrayList();
@Mock private BlockHeaderValidator<IbftContext> headerValidator; @Mock private BlockValidator<IbftContext> blockValidator;
private final BlockHeader parentHeader = mock(BlockHeader.class); private final BlockHeader parentHeader = mock(BlockHeader.class);
private final ConsensusRoundIdentifier roundIdentifier = new ConsensusRoundIdentifier(2, 0); private final ConsensusRoundIdentifier roundIdentifier = new ConsensusRoundIdentifier(2, 0);
private MessageValidator validator; private MessageValidator validator;
@ -82,30 +84,27 @@ public class MessageValidatorTest {
validators, validators,
Util.publicKeyToAddress(proposerKey.getPublicKey()), Util.publicKeyToAddress(proposerKey.getPublicKey()),
roundIdentifier, roundIdentifier,
headerValidator, blockValidator,
protocolContext, protocolContext,
parentHeader); parentHeader);
when(block.getHash()).thenReturn(Hash.fromHexStringLenient("1")); when(block.getHash()).thenReturn(Hash.fromHexStringLenient("1"));
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
.thenReturn(Optional.of(new BlockProcessingOutputs(null, null)));
insertRoundToBlockHeader(0); insertRoundToBlockHeader(0);
} }
private void insertRoundToBlockHeader(final int round) { private void insertRoundToBlockHeader(final int round) {
final IbftExtraData extraData = final IbftExtraData extraData =
new IbftExtraData( new IbftExtraData(
BytesValue.wrap(new byte[32]), BytesValue.wrap(new byte[32]), Collections.emptyList(), empty(), round, validators);
Collections.emptyList(),
Optional.empty(),
round,
validators);
final BlockHeader header = mock(BlockHeader.class); final BlockHeader header = mock(BlockHeader.class);
when(header.getExtraData()).thenReturn(extraData.encode()); when(header.getExtraData()).thenReturn(extraData.encode());
when(block.getHeader()).thenReturn(header); when(block.getHeader()).thenReturn(header);
} }
@Test @Test
public void receivingAPrepareMessageBeforePrePrepareFails() { public void receivingAPrepareMessageBeforeProposalFails() {
final SignedData<PreparePayload> prepareMsg = final SignedData<PreparePayload> prepareMsg =
proposerMessageFactory.createSignedPreparePayload(roundIdentifier, Hash.ZERO); proposerMessageFactory.createSignedPreparePayload(roundIdentifier, Hash.ZERO);
@ -113,7 +112,7 @@ public class MessageValidatorTest {
} }
@Test @Test
public void receivingACommitMessageBeforePreprepareFails() { public void receivingACommitMessageBeforeProposalFails() {
final SignedData<CommitPayload> commitMsg = final SignedData<CommitPayload> commitMsg =
proposerMessageFactory.createSignedCommitPayload( proposerMessageFactory.createSignedCommitPayload(
roundIdentifier, Hash.ZERO, SECP256K1.sign(Hash.ZERO, proposerKey)); roundIdentifier, Hash.ZERO, SECP256K1.sign(Hash.ZERO, proposerKey));
@ -122,55 +121,49 @@ public class MessageValidatorTest {
} }
@Test @Test
public void receivingPreprepareMessageFromNonProposerFails() { public void receivingProposalMessageFromNonProposerFails() {
final SignedData<ProposalPayload> preprepareMsg = final SignedData<ProposalPayload> proposalMsg =
validatorMessageFactory.createSignedProposalPayload(roundIdentifier, mock(Block.class)); validatorMessageFactory.createSignedProposalPayload(roundIdentifier, mock(Block.class));
assertThat(validator.addSignedProposalPayload(preprepareMsg)).isFalse(); assertThat(validator.addSignedProposalPayload(proposalMsg)).isFalse();
} }
@Test @Test
public void receivingPreprepareMessageWithIllegalBlockFails() { public void receivingProposalMessageWithIllegalBlockFails() {
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(false); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any())).thenReturn(empty());
final SignedData<ProposalPayload> preprepareMsg = final SignedData<ProposalPayload> proposalMsg =
proposerMessageFactory.createSignedProposalPayload(roundIdentifier, mock(Block.class)); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, mock(Block.class));
assertThat(validator.addSignedProposalPayload(preprepareMsg)).isFalse(); assertThat(validator.addSignedProposalPayload(proposalMsg)).isFalse();
} }
@Test @Test
public void receivingPrepareFromProposerFails() { public void receivingPrepareFromProposerFails() {
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); final SignedData<ProposalPayload> proposalMsg =
final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
final SignedData<PreparePayload> prepareMsg = final SignedData<PreparePayload> prepareMsg =
proposerMessageFactory.createSignedPreparePayload(roundIdentifier, block.getHash()); proposerMessageFactory.createSignedPreparePayload(roundIdentifier, block.getHash());
assertThat(validator.addSignedProposalPayload(preprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(proposalMsg)).isTrue();
assertThat(validator.validatePrepareMessage(prepareMsg)).isFalse(); assertThat(validator.validatePrepareMessage(prepareMsg)).isFalse();
} }
@Test @Test
public void receivingPrepareFromNonValidatorFails() { public void receivingPrepareFromNonValidatorFails() {
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); final SignedData<ProposalPayload> proposalMsg =
final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
final SignedData<PreparePayload> prepareMsg = final SignedData<PreparePayload> prepareMsg =
nonValidatorMessageFactory.createSignedPreparePayload(roundIdentifier, block.getHash()); nonValidatorMessageFactory.createSignedPreparePayload(roundIdentifier, block.getHash());
assertThat(validator.addSignedProposalPayload(preprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(proposalMsg)).isTrue();
assertThat(validator.validatePrepareMessage(prepareMsg)).isFalse(); assertThat(validator.validatePrepareMessage(prepareMsg)).isFalse();
} }
@Test @Test
public void receivingMessagesWithDifferentRoundIdFromPreprepareFails() { public void receivingMessagesWithDifferentRoundIdFromProposalFails() {
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); final SignedData<ProposalPayload> proposalMsg =
final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
final ConsensusRoundIdentifier invalidRoundIdentifier = final ConsensusRoundIdentifier invalidRoundIdentifier =
@ -182,44 +175,38 @@ public class MessageValidatorTest {
validatorMessageFactory.createSignedCommitPayload( validatorMessageFactory.createSignedCommitPayload(
invalidRoundIdentifier, block.getHash(), SECP256K1.sign(block.getHash(), proposerKey)); invalidRoundIdentifier, block.getHash(), SECP256K1.sign(block.getHash(), proposerKey));
assertThat(validator.addSignedProposalPayload(preprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(proposalMsg)).isTrue();
assertThat(validator.validatePrepareMessage(prepareMsg)).isFalse(); assertThat(validator.validatePrepareMessage(prepareMsg)).isFalse();
assertThat(validator.validateCommmitMessage(commitMsg)).isFalse(); assertThat(validator.validateCommmitMessage(commitMsg)).isFalse();
} }
@Test @Test
public void receivingPrepareNonProposerValidatorWithCorrectRoundIsSuccessful() { public void receivingPrepareNonProposerValidatorWithCorrectRoundIsSuccessful() {
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); final SignedData<ProposalPayload> proposalMsg =
final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
final SignedData<PreparePayload> prepareMsg = final SignedData<PreparePayload> prepareMsg =
validatorMessageFactory.createSignedPreparePayload(roundIdentifier, block.getHash()); validatorMessageFactory.createSignedPreparePayload(roundIdentifier, block.getHash());
assertThat(validator.addSignedProposalPayload(preprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(proposalMsg)).isTrue();
assertThat(validator.validatePrepareMessage(prepareMsg)).isTrue(); assertThat(validator.validatePrepareMessage(prepareMsg)).isTrue();
} }
@Test @Test
public void receivingACommitMessageWithAnInvalidCommitSealFails() { public void receivingACommitMessageWithAnInvalidCommitSealFails() {
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); final SignedData<ProposalPayload> proposalMsg =
final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
final SignedData<CommitPayload> commitMsg = final SignedData<CommitPayload> commitMsg =
proposerMessageFactory.createSignedCommitPayload( proposerMessageFactory.createSignedCommitPayload(
roundIdentifier, block.getHash(), SECP256K1.sign(block.getHash(), nonValidatorKey)); roundIdentifier, block.getHash(), SECP256K1.sign(block.getHash(), nonValidatorKey));
assertThat(validator.addSignedProposalPayload(preprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(proposalMsg)).isTrue();
assertThat(validator.validateCommmitMessage(commitMsg)).isFalse(); assertThat(validator.validateCommmitMessage(commitMsg)).isFalse();
} }
@Test @Test
public void commitMessageContainingValidSealFromValidatorIsSuccessful() { public void commitMessageContainingValidSealFromValidatorIsSuccessful() {
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); final SignedData<ProposalPayload> proposalMsg =
final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
final SignedData<CommitPayload> proposerCommitMsg = final SignedData<CommitPayload> proposerCommitMsg =
@ -230,58 +217,52 @@ public class MessageValidatorTest {
validatorMessageFactory.createSignedCommitPayload( validatorMessageFactory.createSignedCommitPayload(
roundIdentifier, block.getHash(), SECP256K1.sign(block.getHash(), validatorKey)); roundIdentifier, block.getHash(), SECP256K1.sign(block.getHash(), validatorKey));
assertThat(validator.addSignedProposalPayload(preprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(proposalMsg)).isTrue();
assertThat(validator.validateCommmitMessage(proposerCommitMsg)).isTrue(); assertThat(validator.validateCommmitMessage(proposerCommitMsg)).isTrue();
assertThat(validator.validateCommmitMessage(validatorCommitMsg)).isTrue(); assertThat(validator.validateCommmitMessage(validatorCommitMsg)).isTrue();
} }
@Test @Test
public void subsequentPreprepareHasDifferentSenderFails() { public void subsequentProposalHasDifferentSenderFails() {
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); final SignedData<ProposalPayload> proposalMsg =
final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
assertThat(validator.addSignedProposalPayload(preprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(proposalMsg)).isTrue();
final SignedData<ProposalPayload> secondPreprepareMsg = final SignedData<ProposalPayload> secondProposalMsg =
validatorMessageFactory.createSignedProposalPayload(roundIdentifier, block); validatorMessageFactory.createSignedProposalPayload(roundIdentifier, block);
assertThat(validator.addSignedProposalPayload(secondPreprepareMsg)).isFalse(); assertThat(validator.addSignedProposalPayload(secondProposalMsg)).isFalse();
} }
@Test @Test
public void subsequentPreprepareHasDifferentContentFails() { public void subsequentProposalHasDifferentContentFails() {
final SignedData<ProposalPayload> proposalMsg =
final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
assertThat(validator.addSignedProposalPayload(preprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(proposalMsg)).isTrue();
final ConsensusRoundIdentifier newRoundIdentifier = new ConsensusRoundIdentifier(3, 0); final ConsensusRoundIdentifier newRoundIdentifier = new ConsensusRoundIdentifier(3, 0);
final SignedData<ProposalPayload> secondPreprepareMsg = final SignedData<ProposalPayload> secondProposalMsg =
proposerMessageFactory.createSignedProposalPayload(newRoundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(newRoundIdentifier, block);
assertThat(validator.addSignedProposalPayload(secondPreprepareMsg)).isFalse(); assertThat(validator.addSignedProposalPayload(secondProposalMsg)).isFalse();
} }
@Test @Test
public void subsequentPreprepareHasIdenticalSenderAndContentIsSuccessful() { public void subsequentProposalHasIdenticalSenderAndContentIsSuccessful() {
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); final SignedData<ProposalPayload> proposalMsg =
final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
assertThat(validator.addSignedProposalPayload(preprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(proposalMsg)).isTrue();
final SignedData<ProposalPayload> secondPreprepareMsg = final SignedData<ProposalPayload> secondProposalMsg =
proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
assertThat(validator.addSignedProposalPayload(secondPreprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(secondProposalMsg)).isTrue();
} }
@Test @Test
public void blockRoundMisMatchWithMessageRoundFails() { public void blockRoundMisMatchWithMessageRoundFails() {
insertRoundToBlockHeader(roundIdentifier.getRoundNumber() + 1); insertRoundToBlockHeader(roundIdentifier.getRoundNumber() + 1);
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); final SignedData<ProposalPayload> proposalMsg =
final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
assertThat(validator.addSignedProposalPayload(preprepareMsg)).isFalse(); assertThat(validator.addSignedProposalPayload(proposalMsg)).isFalse();
} }
} }

@ -22,7 +22,6 @@ import tech.pegasys.pantheon.consensus.common.VoteProposer;
import tech.pegasys.pantheon.consensus.common.VoteTally; import tech.pegasys.pantheon.consensus.common.VoteTally;
import tech.pegasys.pantheon.consensus.common.VoteTallyUpdater; import tech.pegasys.pantheon.consensus.common.VoteTallyUpdater;
import tech.pegasys.pantheon.consensus.ibft.BlockTimer; import tech.pegasys.pantheon.consensus.ibft.BlockTimer;
import tech.pegasys.pantheon.consensus.ibft.IbftBlockHeaderValidationRulesetFactory;
import tech.pegasys.pantheon.consensus.ibft.IbftBlockInterface; import tech.pegasys.pantheon.consensus.ibft.IbftBlockInterface;
import tech.pegasys.pantheon.consensus.ibft.IbftContext; import tech.pegasys.pantheon.consensus.ibft.IbftContext;
import tech.pegasys.pantheon.consensus.ibft.IbftEventQueue; import tech.pegasys.pantheon.consensus.ibft.IbftEventQueue;
@ -65,7 +64,6 @@ import tech.pegasys.pantheon.ethereum.eth.sync.state.SyncState;
import tech.pegasys.pantheon.ethereum.eth.transactions.TransactionPoolFactory; import tech.pegasys.pantheon.ethereum.eth.transactions.TransactionPoolFactory;
import tech.pegasys.pantheon.ethereum.jsonrpc.RpcApi; import tech.pegasys.pantheon.ethereum.jsonrpc.RpcApi;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.JsonRpcMethod; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.JsonRpcMethod;
import tech.pegasys.pantheon.ethereum.mainnet.BlockHeaderValidator;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.p2p.api.ProtocolManager; import tech.pegasys.pantheon.ethereum.p2p.api.ProtocolManager;
import tech.pegasys.pantheon.ethereum.p2p.config.SubProtocolConfiguration; import tech.pegasys.pantheon.ethereum.p2p.config.SubProtocolConfiguration;
@ -202,10 +200,6 @@ public class IbftPantheonController implements PantheonController<IbftContext> {
final ValidatorPeers peers = final ValidatorPeers peers =
new ValidatorPeers(protocolContext.getConsensusState().getVoteTally()); new ValidatorPeers(protocolContext.getConsensusState().getVoteTally());
final BlockHeaderValidator<IbftContext> blockHeaderValidator =
IbftBlockHeaderValidationRulesetFactory.ibftProposedBlockValidator(
ibftConfig.getBlockPeriodSeconds());
final Subscribers<MinedBlockObserver> minedBlockObservers = new Subscribers<>(); final Subscribers<MinedBlockObserver> minedBlockObservers = new Subscribers<>();
minedBlockObservers.subscribe(ethProtocolManager); minedBlockObservers.subscribe(ethProtocolManager);
@ -227,11 +221,10 @@ public class IbftPantheonController implements PantheonController<IbftContext> {
Clock.systemUTC()), Clock.systemUTC()),
blockCreatorFactory, blockCreatorFactory,
new MessageFactory(nodeKeys), new MessageFactory(nodeKeys),
blockHeaderValidator,
Clock.systemUTC()); Clock.systemUTC());
final MessageValidatorFactory messageValidatorFactory = final MessageValidatorFactory messageValidatorFactory =
new MessageValidatorFactory(proposerSelector, blockHeaderValidator, protocolContext); new MessageValidatorFactory(proposerSelector, protocolSchedule, protocolContext);
final IbftController ibftController = final IbftController ibftController =
new IbftController( new IbftController(

Loading…
Cancel
Save