Skip to content
This repository has been archived by the owner on Sep 26, 2019. It is now read-only.

IBFT ensure non-validator does not partake in consensus #627

Merged
merged 4 commits into from
Jan 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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.
*/
package tech.pegasys.pantheon.consensus.ibft.statemachine;

import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibft.ibftevent.RoundExpiry;
import tech.pegasys.pantheon.consensus.ibft.payload.CommitPayload;
import tech.pegasys.pantheon.consensus.ibft.payload.NewRoundPayload;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparePayload;
import tech.pegasys.pantheon.consensus.ibft.payload.ProposalPayload;
import tech.pegasys.pantheon.consensus.ibft.payload.RoundChangePayload;
import tech.pegasys.pantheon.consensus.ibft.payload.SignedData;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;

public interface BlockHeightManager {

void start();

void handleBlockTimerExpiry(ConsensusRoundIdentifier roundIdentifier);

void roundExpired(RoundExpiry expire);

void handleProposalPayload(SignedData<ProposalPayload> signedPayload);

void handlePreparePayload(SignedData<PreparePayload> signedPayload);

void handleCommitPayload(SignedData<CommitPayload> payload);

void handleRoundChangePayload(SignedData<RoundChangePayload> signedPayload);

void handleNewRoundPayload(SignedData<NewRoundPayload> signedPayload);

long getChainHeight();

BlockHeader getParentBlockHeader();
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,7 @@
* and sends a Proposal message. If the round times out prior to importing a block, this class is
* responsible for creating a RoundChange message and transmitting it.
*/
public class IbftBlockHeightManager {

protected enum MessageAge {
PRIOR_ROUND,
CURRENT_ROUND,
FUTURE_ROUND
}
public class IbftBlockHeightManager implements BlockHeightManager {

private static final Logger LOG = LogManager.getLogger();

Expand Down Expand Up @@ -107,13 +101,15 @@ public IbftBlockHeightManager(
messageValidatorFactory.createMessageValidator(roundIdentifier, parentHeader));
}

@Override
public void start() {
startNewRound(0);
if (finalState.isLocalNodeProposerForRound(currentRound.getRoundIdentifier())) {
blockTimer.startTimer(currentRound.getRoundIdentifier(), parentHeader);
}
}

@Override
public void handleBlockTimerExpiry(final ConsensusRoundIdentifier roundIdentifier) {
if (roundIdentifier.equals(currentRound.getRoundIdentifier())) {
currentRound.createAndSendProposalMessage(clock.millis() / 1000);
Expand All @@ -125,6 +121,7 @@ public void handleBlockTimerExpiry(final ConsensusRoundIdentifier roundIdentifie
}
}

@Override
public void roundExpired(final RoundExpiry expire) {
if (!expire.getView().equals(currentRound.getRoundIdentifier())) {
LOG.info("Ignoring Round timer expired which does not match current round.");
Expand All @@ -151,18 +148,21 @@ public void roundExpired(final RoundExpiry expire) {
handleRoundChangePayload(localRoundChange);
}

@Override
public void handleProposalPayload(final SignedData<ProposalPayload> signedPayload) {
LOG.info("Received a Proposal Payload.");
actionOrBufferMessage(
signedPayload, currentRound::handleProposalMessage, RoundState::setProposedBlock);
}

@Override
public void handlePreparePayload(final SignedData<PreparePayload> signedPayload) {
LOG.info("Received a prepare Payload.");
actionOrBufferMessage(
signedPayload, currentRound::handlePrepareMessage, RoundState::addPrepareMessage);
}

@Override
public void handleCommitPayload(final SignedData<CommitPayload> payload) {
LOG.info("Received a commit Payload.");
actionOrBufferMessage(payload, currentRound::handleCommitMessage, RoundState::addCommitMessage);
Expand All @@ -185,6 +185,7 @@ private <T extends Payload> void actionOrBufferMessage(
}
}

@Override
public void handleRoundChangePayload(final SignedData<RoundChangePayload> signedPayload) {
final ConsensusRoundIdentifier targetRound = signedPayload.getPayload().getRoundIdentifier();
LOG.info("Received a RoundChange Payload for {}", targetRound.toString());
Expand Down Expand Up @@ -223,6 +224,7 @@ private void startNewRound(final int roundNumber) {
roundTimer.startTimer(currentRound.getRoundIdentifier());
}

@Override
public void handleNewRoundPayload(final SignedData<NewRoundPayload> signedPayload) {
final NewRoundPayload payload = signedPayload.getPayload();
final MessageAge messageAge = determineAgeOfPayload(payload);
Expand All @@ -241,10 +243,12 @@ public void handleNewRoundPayload(final SignedData<NewRoundPayload> signedPayloa
}
}

@Override
public long getChainHeight() {
return currentRound.getRoundIdentifier().getSequenceNumber();
}

@Override
public BlockHeader getParentBlockHeader() {
return parentHeader;
}
Expand All @@ -259,4 +263,10 @@ private MessageAge determineAgeOfPayload(final Payload payload) {
}
return PRIOR_ROUND;
}

public enum MessageAge {
PRIOR_ROUND,
CURRENT_ROUND,
FUTURE_ROUND
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,19 @@ public IbftBlockHeightManagerFactory(
this.messageValidatorFactory = messageValidatorFactory;
}

public IbftBlockHeightManager create(final BlockHeader parentHeader) {
public BlockHeightManager create(final BlockHeader parentHeader) {
if (finalState.isLocalNodeValidator()) {
return createFullBlockHeightManager(parentHeader);
} else {
return createNoOpBlockHeightManager(parentHeader);
}
}

private BlockHeightManager createNoOpBlockHeightManager(final BlockHeader parentHeader) {
return new NoOpBlockHeightManager(parentHeader);
}

private BlockHeightManager createFullBlockHeightManager(final BlockHeader parentHeader) {
return new IbftBlockHeightManager(
parentHeader,
finalState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class IbftController {
private final IbftFinalState ibftFinalState;
private final IbftBlockHeightManagerFactory ibftBlockHeightManagerFactory;
private final Map<Long, List<Message>> futureMessages;
private IbftBlockHeightManager currentHeightManager;
private BlockHeightManager currentHeightManager;
private final IbftGossip gossiper;

public IbftController(
Expand Down Expand Up @@ -188,7 +188,7 @@ private void startNewHeightManager(final BlockHeader parentHeader) {
private boolean processMessage(final SignedData<? extends Payload> msg, final Message rawMsg) {
final ConsensusRoundIdentifier msgRoundIdentifier = msg.getPayload().getRoundIdentifier();
if (isMsgForCurrentHeight(msgRoundIdentifier)) {
return isMsgFromKnownValidator(msg);
return isMsgFromKnownValidator(msg) && ibftFinalState.isLocalNodeValidator();
} else if (isMsgForFutureChainHeight(msgRoundIdentifier)) {
addMessageToFutureMessageBuffer(msgRoundIdentifier.getSequenceNumber(), rawMsg);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ public boolean isLocalNodeProposerForRound(final ConsensusRoundIdentifier roundI
return getProposerForRound(roundIdentifier).equals(localAddress);
}

public boolean isLocalNodeValidator() {
return getValidators().contains(localAddress);
}

public ValidatorMulticaster getValidatorMulticaster() {
return validatorMulticaster;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* 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.
*/
package tech.pegasys.pantheon.consensus.ibft.statemachine;

import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibft.ibftevent.RoundExpiry;
import tech.pegasys.pantheon.consensus.ibft.payload.CommitPayload;
import tech.pegasys.pantheon.consensus.ibft.payload.NewRoundPayload;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparePayload;
import tech.pegasys.pantheon.consensus.ibft.payload.ProposalPayload;
import tech.pegasys.pantheon.consensus.ibft.payload.RoundChangePayload;
import tech.pegasys.pantheon.consensus.ibft.payload.SignedData;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;

public class NoOpBlockHeightManager implements BlockHeightManager {

private final BlockHeader parentHeader;

public NoOpBlockHeightManager(final BlockHeader parentHeader) {
this.parentHeader = parentHeader;
}

@Override
public void start() {}

@Override
public void handleBlockTimerExpiry(final ConsensusRoundIdentifier roundIdentifier) {}

@Override
public void roundExpired(final RoundExpiry expire) {}

@Override
public void handleProposalPayload(final SignedData<ProposalPayload> signedPayload) {}

@Override
public void handlePreparePayload(final SignedData<PreparePayload> signedPayload) {}

@Override
public void handleCommitPayload(final SignedData<CommitPayload> payload) {}

@Override
public void handleRoundChangePayload(final SignedData<RoundChangePayload> signedPayload) {}

@Override
public void handleNewRoundPayload(final SignedData<NewRoundPayload> signedPayload) {}

@Override
public long getChainHeight() {
return parentHeader.getNumber() + 1;
}

@Override
public BlockHeader getParentBlockHeader() {
return parentHeader;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public class IbftControllerTest {
@Mock private IbftBlockHeightManagerFactory blockHeightManagerFactory;
@Mock private BlockHeader chainHeadBlockHeader;
@Mock private BlockHeader nextBlock;
@Mock private IbftBlockHeightManager blockHeightManager;
@Mock private BlockHeightManager blockHeightManager;

@Mock private SignedData<ProposalPayload> signedProposal;
private Message proposalMessage;
Expand Down Expand Up @@ -116,6 +116,8 @@ public void setup() {
when(blockHeightManager.getParentBlockHeader()).thenReturn(chainHeadBlockHeader);

when(nextBlock.getNumber()).thenReturn(2L);

when(ibftFinalState.isLocalNodeValidator()).thenReturn(true);
}

@Test
Expand Down