diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftFinalState.java b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftFinalState.java new file mode 100644 index 0000000000..8912800d15 --- /dev/null +++ b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftFinalState.java @@ -0,0 +1,120 @@ +/* + * Copyright 2018 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 static tech.pegasys.pantheon.consensus.ibft.IbftHelpers.calculateRequiredValidatorQuorum; + +import tech.pegasys.pantheon.consensus.common.ValidatorProvider; +import tech.pegasys.pantheon.consensus.common.VoteTally; +import tech.pegasys.pantheon.consensus.ibft.BlockTimer; +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.blockcreation.IbftBlockCreatorFactory; +import tech.pegasys.pantheon.consensus.ibft.blockcreation.ProposerSelector; +import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.MessageFactory; +import tech.pegasys.pantheon.consensus.ibft.network.IbftNetworkPeers; +import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; +import tech.pegasys.pantheon.ethereum.core.Address; +import tech.pegasys.pantheon.ethereum.mainnet.BlockHeaderValidator; + +import java.util.Collection; + +/** This is the full data set, or context, required for many of the aspects of the IBFT workflow. */ +public class IbftFinalState { + private final ValidatorProvider validatorProvider; + private final KeyPair nodeKeys; + private final Address localAddress; + private final ProposerSelector proposerSelector; + private final IbftNetworkPeers peers; + private final RoundTimer roundTimer; + private final BlockTimer blockTimer; + private final IbftBlockCreatorFactory blockCreatorFactory; + private final MessageFactory messageFactory; + private final BlockHeaderValidator ibftContextBlockHeaderValidator; + + public IbftFinalState( + final VoteTally validatorProvider, + final KeyPair nodeKeys, + final Address localAddress, + final ProposerSelector proposerSelector, + final IbftNetworkPeers peers, + final RoundTimer roundTimer, + final BlockTimer blockTimer, + final IbftBlockCreatorFactory blockCreatorFactory, + final MessageFactory messageFactory, + final BlockHeaderValidator ibftContextBlockHeaderValidator) { + this.validatorProvider = validatorProvider; + this.nodeKeys = nodeKeys; + this.localAddress = localAddress; + this.proposerSelector = proposerSelector; + this.peers = peers; + this.roundTimer = roundTimer; + this.blockTimer = blockTimer; + this.blockCreatorFactory = blockCreatorFactory; + this.messageFactory = messageFactory; + this.ibftContextBlockHeaderValidator = ibftContextBlockHeaderValidator; + } + + public int getQuorumSize() { + return calculateRequiredValidatorQuorum(validatorProvider.getValidators().size()); + } + + public Collection
getValidators() { + return validatorProvider.getValidators(); + } + + public KeyPair getNodeKeys() { + return nodeKeys; + } + + public Address getLocalAddress() { + return localAddress; + } + + public ProposerSelector getProposerSelector() { + return proposerSelector; + } + + public boolean isLocalNodeProposerForRound(final ConsensusRoundIdentifier roundIdentifier) { + return getProposerForRound(roundIdentifier).equals(localAddress); + } + + public IbftNetworkPeers getPeers() { + return peers; + } + + public RoundTimer getRoundTimer() { + return roundTimer; + } + + public BlockTimer getBlockTimer() { + return blockTimer; + } + + public IbftBlockCreatorFactory getBlockCreatorFactory() { + return blockCreatorFactory; + } + + public MessageFactory getMessageFactory() { + return messageFactory; + } + + public Address getProposerForRound(final ConsensusRoundIdentifier roundIdentifier) { + return proposerSelector.selectProposerForRound(roundIdentifier); + } + + public BlockHeaderValidator getBlockHeaderValidator() { + return ibftContextBlockHeaderValidator; + } +} diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftHelpersTest.java b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftHelpersTest.java new file mode 100644 index 0000000000..7a29047274 --- /dev/null +++ b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftHelpersTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2018 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; + +import static org.assertj.core.api.Assertions.assertThat; +import static tech.pegasys.pantheon.consensus.ibft.IbftHelpers.calculateRequiredValidatorQuorum; + +import org.junit.Test; + +public class IbftHelpersTest { + + @Test + public void calculateRequiredValidatorQuorum1Validator() { + assertThat(calculateRequiredValidatorQuorum(1)).isEqualTo(1); + } + + @Test + public void calculateRequiredValidatorQuorum2Validator() { + assertThat(calculateRequiredValidatorQuorum(2)).isEqualTo(2); + } + + @Test + public void calculateRequiredValidatorQuorum3Validator() { + assertThat(calculateRequiredValidatorQuorum(3)).isEqualTo(2); + } + + @Test + public void calculateRequiredValidatorQuorum4Validator() { + assertThat(calculateRequiredValidatorQuorum(4)).isEqualTo(3); + } + + @Test + public void calculateRequiredValidatorQuorum5Validator() { + assertThat(calculateRequiredValidatorQuorum(5)).isEqualTo(4); + } + + @Test + public void calculateRequiredValidatorQuorum7Validator() { + assertThat(calculateRequiredValidatorQuorum(7)).isEqualTo(5); + } + + @Test + public void calculateRequiredValidatorQuorum10Validator() { + assertThat(calculateRequiredValidatorQuorum(10)).isEqualTo(7); + } + + @Test + public void calculateRequiredValidatorQuorum15Validator() { + assertThat(calculateRequiredValidatorQuorum(15)).isEqualTo(10); + } + + @Test + public void calculateRequiredValidatorQuorum20Validator() { + assertThat(calculateRequiredValidatorQuorum(20)).isEqualTo(14); + } +}