Added TerminatedRoundArtefacts (#756)

Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
tmohay 6 years ago committed by GitHub
parent 4a7b9823ad
commit 46c888c792
  1. 7
      consensus/ibft/src/integration-test/java/tech/pegasys/pantheon/consensus/ibft/support/RoundSpecificPeers.java
  2. 18
      consensus/ibft/src/integration-test/java/tech/pegasys/pantheon/consensus/ibft/support/TestHelpers.java
  3. 7
      consensus/ibft/src/integration-test/java/tech/pegasys/pantheon/consensus/ibft/support/ValidatorPeer.java
  4. 16
      consensus/ibft/src/integration-test/java/tech/pegasys/pantheon/consensus/ibft/tests/ReceivedNewRoundTest.java
  5. 33
      consensus/ibft/src/integration-test/java/tech/pegasys/pantheon/consensus/ibft/tests/RoundChangeTest.java
  6. 5
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/messagewrappers/Proposal.java
  7. 6
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/network/IbftMessageTransmitter.java
  8. 8
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/payload/MessageFactory.java
  9. 16
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftBlockHeightManager.java
  10. 4
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftRound.java
  11. 29
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/RoundState.java
  12. 42
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/TerminatedRoundArtefacts.java
  13. 41
      consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftHelpersTest.java
  14. 10
      consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java
  15. 8
      consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftRoundTest.java
  16. 17
      consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/statemachine/RoundChangeManagerTest.java
  17. 23
      consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/statemachine/RoundStateTest.java
  18. 50
      consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/validation/NewRoundSignedDataValidatorTest.java
  19. 61
      consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/validation/RoundChangeSignedDataValidatorTest.java

@ -27,9 +27,9 @@ import tech.pegasys.pantheon.consensus.ibft.messagewrappers.IbftMessage;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.RoundChange;
import tech.pegasys.pantheon.consensus.ibft.payload.Payload;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparePayload;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparedCertificate;
import tech.pegasys.pantheon.consensus.ibft.payload.RoundChangePayload;
import tech.pegasys.pantheon.consensus.ibft.payload.SignedData;
import tech.pegasys.pantheon.consensus.ibft.statemachine.TerminatedRoundArtefacts;
import tech.pegasys.pantheon.crypto.SECP256K1.Signature;
import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.p2p.api.MessageData;
@ -113,13 +113,14 @@ public class RoundSpecificPeers {
}
public List<SignedData<RoundChangePayload>> createSignedRoundChangePayload(
final ConsensusRoundIdentifier roundId, final PreparedCertificate preparedCertificate) {
final ConsensusRoundIdentifier roundId,
final TerminatedRoundArtefacts terminatedRoundArtefacts) {
return peers
.stream()
.map(
p ->
p.getMessageFactory()
.createSignedRoundChangePayload(roundId, Optional.of(preparedCertificate))
.createSignedRoundChangePayload(roundId, Optional.of(terminatedRoundArtefacts))
.getSignedPayload())
.collect(Collectors.toList());
}

@ -16,19 +16,21 @@ import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibft.IbftBlockHashing;
import tech.pegasys.pantheon.consensus.ibft.IbftExtraData;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.NewRound;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Prepare;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Proposal;
import tech.pegasys.pantheon.consensus.ibft.payload.CommitPayload;
import tech.pegasys.pantheon.consensus.ibft.payload.MessageFactory;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparedCertificate;
import tech.pegasys.pantheon.consensus.ibft.payload.RoundChangeCertificate;
import tech.pegasys.pantheon.consensus.ibft.payload.RoundChangePayload;
import tech.pegasys.pantheon.consensus.ibft.payload.SignedData;
import tech.pegasys.pantheon.consensus.ibft.statemachine.TerminatedRoundArtefacts;
import tech.pegasys.pantheon.crypto.SECP256K1;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.crypto.SECP256K1.Signature;
import tech.pegasys.pantheon.ethereum.core.Block;
import java.util.List;
import java.util.stream.Collectors;
public class TestHelpers {
@ -49,17 +51,17 @@ public class TestHelpers {
.getSignedPayload();
}
public static PreparedCertificate createValidPreparedCertificate(
public static TerminatedRoundArtefacts createValidTerminatedRoundArtefacts(
final TestContext context, final ConsensusRoundIdentifier preparedRound, final Block block) {
final RoundSpecificPeers peers = context.roundSpecificPeers(preparedRound);
return new PreparedCertificate(
return new TerminatedRoundArtefacts(
peers.getProposer().getMessageFactory().createSignedProposalPayload(preparedRound, block),
peers
.getProposer()
.getMessageFactory()
.createSignedProposalPayload(preparedRound, block)
.getSignedPayload(),
peers.createSignedPreparePayloadOfNonProposing(preparedRound, block.getHash()));
.createSignedPreparePayloadOfNonProposing(preparedRound, block.getHash())
.stream()
.map(Prepare::new)
.collect(Collectors.toList()));
}
public static NewRound injectEmptyNewRound(

@ -26,10 +26,10 @@ import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Prepare;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Proposal;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.RoundChange;
import tech.pegasys.pantheon.consensus.ibft.payload.MessageFactory;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparedCertificate;
import tech.pegasys.pantheon.consensus.ibft.payload.ProposalPayload;
import tech.pegasys.pantheon.consensus.ibft.payload.RoundChangeCertificate;
import tech.pegasys.pantheon.consensus.ibft.payload.SignedData;
import tech.pegasys.pantheon.consensus.ibft.statemachine.TerminatedRoundArtefacts;
import tech.pegasys.pantheon.crypto.SECP256K1;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.crypto.SECP256K1.Signature;
@ -120,9 +120,10 @@ public class ValidatorPeer {
}
public RoundChange injectRoundChange(
final ConsensusRoundIdentifier rId, final Optional<PreparedCertificate> preparedCertificate) {
final ConsensusRoundIdentifier rId,
final Optional<TerminatedRoundArtefacts> terminatedRoundArtefacts) {
final RoundChange payload =
messageFactory.createSignedRoundChangePayload(rId, preparedCertificate);
messageFactory.createSignedRoundChangePayload(rId, terminatedRoundArtefacts);
injectMessage(RoundChangeMessageData.create(payload));
return payload;
}

@ -12,17 +12,17 @@
*/
package tech.pegasys.pantheon.consensus.ibft.tests;
import static tech.pegasys.pantheon.consensus.ibft.support.TestHelpers.createValidPreparedCertificate;
import static tech.pegasys.pantheon.consensus.ibft.support.TestHelpers.createValidTerminatedRoundArtefacts;
import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Commit;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Prepare;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Proposal;
import tech.pegasys.pantheon.consensus.ibft.payload.MessageFactory;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparedCertificate;
import tech.pegasys.pantheon.consensus.ibft.payload.RoundChangeCertificate;
import tech.pegasys.pantheon.consensus.ibft.payload.RoundChangePayload;
import tech.pegasys.pantheon.consensus.ibft.payload.SignedData;
import tech.pegasys.pantheon.consensus.ibft.statemachine.TerminatedRoundArtefacts;
import tech.pegasys.pantheon.consensus.ibft.support.RoundSpecificPeers;
import tech.pegasys.pantheon.consensus.ibft.support.TestContext;
import tech.pegasys.pantheon.consensus.ibft.support.TestContextBuilder;
@ -111,11 +111,11 @@ public class ReceivedNewRoundTest {
final Block reproposedBlock = context.createBlockForProposalFromChainHead(1, 15);
final ConsensusRoundIdentifier nextRoundId = new ConsensusRoundIdentifier(1, 1);
final PreparedCertificate preparedCertificate =
createValidPreparedCertificate(context, roundId, initialBlock);
final TerminatedRoundArtefacts terminatedRoundArtefacts =
createValidTerminatedRoundArtefacts(context, roundId, initialBlock);
final List<SignedData<RoundChangePayload>> roundChanges =
peers.createSignedRoundChangePayload(nextRoundId, preparedCertificate);
peers.createSignedRoundChangePayload(nextRoundId, terminatedRoundArtefacts);
final ValidatorPeer nextProposer = context.roundSpecificPeers(nextRoundId).getProposer();
@ -164,11 +164,11 @@ public class ReceivedNewRoundTest {
final Block reproposedBlock = context.createBlockForProposalFromChainHead(1, 15);
final ConsensusRoundIdentifier nextRoundId = new ConsensusRoundIdentifier(1, 1);
final PreparedCertificate preparedCertificate =
createValidPreparedCertificate(context, roundId, initialBlock);
final TerminatedRoundArtefacts terminatedRoundArtefacts =
createValidTerminatedRoundArtefacts(context, roundId, initialBlock);
final List<SignedData<RoundChangePayload>> roundChanges =
peers.createSignedRoundChangePayload(nextRoundId, preparedCertificate);
peers.createSignedRoundChangePayload(nextRoundId, terminatedRoundArtefacts);
final RoundSpecificPeers nextRoles = context.roundSpecificPeers(nextRoundId);
final ValidatorPeer nextProposer = nextRoles.getProposer();

@ -14,7 +14,7 @@ package tech.pegasys.pantheon.consensus.ibft.tests;
import static java.util.Collections.emptyList;
import static java.util.Optional.empty;
import static tech.pegasys.pantheon.consensus.ibft.support.TestHelpers.createValidPreparedCertificate;
import static tech.pegasys.pantheon.consensus.ibft.support.TestHelpers.createValidTerminatedRoundArtefacts;
import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibft.IbftHelpers;
@ -24,10 +24,10 @@ import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Prepare;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Proposal;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.RoundChange;
import tech.pegasys.pantheon.consensus.ibft.payload.MessageFactory;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparedCertificate;
import tech.pegasys.pantheon.consensus.ibft.payload.RoundChangeCertificate;
import tech.pegasys.pantheon.consensus.ibft.payload.RoundChangePayload;
import tech.pegasys.pantheon.consensus.ibft.payload.SignedData;
import tech.pegasys.pantheon.consensus.ibft.statemachine.TerminatedRoundArtefacts;
import tech.pegasys.pantheon.consensus.ibft.support.RoundSpecificPeers;
import tech.pegasys.pantheon.consensus.ibft.support.TestContext;
import tech.pegasys.pantheon.consensus.ibft.support.TestContextBuilder;
@ -130,12 +130,8 @@ public class RoundChangeTest {
localNodeMessageFactory.createSignedRoundChangePayload(
targetRound,
Optional.of(
new PreparedCertificate(
proposal.getSignedPayload(),
Lists.newArrayList(
localPrepareMessage.getSignedPayload(),
p1.getSignedPayload(),
p2.getSignedPayload()))));
new TerminatedRoundArtefacts(
proposal, Lists.newArrayList(localPrepareMessage, p1, p2))));
context.getController().handleRoundExpiry(new RoundExpiry(roundId));
peers.verifyMessagesReceived(expectedTxRoundChange);
@ -173,14 +169,14 @@ public class RoundChangeTest {
public void newRoundMessageContainsBlockOnWhichPeerPrepared() {
final long ARBITRARY_BLOCKTIME = 1500;
final PreparedCertificate earlierPrepCert =
createValidPreparedCertificate(
final TerminatedRoundArtefacts earlierPrepCert =
createValidTerminatedRoundArtefacts(
context,
new ConsensusRoundIdentifier(1, 1),
context.createBlockForProposalFromChainHead(1, ARBITRARY_BLOCKTIME / 2));
final PreparedCertificate bestPrepCert =
createValidPreparedCertificate(
final TerminatedRoundArtefacts bestPrepCert =
createValidTerminatedRoundArtefacts(
context,
new ConsensusRoundIdentifier(1, 2),
context.createBlockForProposalFromChainHead(2, ARBITRARY_BLOCKTIME));
@ -267,8 +263,8 @@ public class RoundChangeTest {
final ConsensusRoundIdentifier targetRound = new ConsensusRoundIdentifier(1, 4);
final PreparedCertificate prepCert =
createValidPreparedCertificate(
final TerminatedRoundArtefacts prepCert =
createValidTerminatedRoundArtefacts(
context,
new ConsensusRoundIdentifier(1, 2),
context.createBlockForProposalFromChainHead(2, ARBITRARY_BLOCKTIME));
@ -333,18 +329,17 @@ public class RoundChangeTest {
final RoundChange rc3 = peers.getNonProposing(2).injectRoundChange(targetRound, empty());
// create illegal RoundChangeMessage
final PreparedCertificate illegalPreparedCertificate =
new PreparedCertificate(
final TerminatedRoundArtefacts illegalTerminatedRoundArtefacts =
new TerminatedRoundArtefacts(
peers
.getNonProposing(0)
.getMessageFactory()
.createSignedProposalPayload(roundId, blockToPropose)
.getSignedPayload(),
.createSignedProposalPayload(roundId, blockToPropose),
emptyList());
peers
.getNonProposing(2)
.injectRoundChange(targetRound, Optional.of(illegalPreparedCertificate));
.injectRoundChange(targetRound, Optional.of(illegalTerminatedRoundArtefacts));
// Ensure no NewRound message is sent.
peers.verifyNoMessagesReceived();

@ -14,10 +14,15 @@ package tech.pegasys.pantheon.consensus.ibft.messagewrappers;
import tech.pegasys.pantheon.consensus.ibft.payload.ProposalPayload;
import tech.pegasys.pantheon.consensus.ibft.payload.SignedData;
import tech.pegasys.pantheon.ethereum.core.Block;
public class Proposal extends IbftMessage<ProposalPayload> {
public Proposal(final SignedData<ProposalPayload> payload) {
super(payload);
}
public Block getBlock() {
return getSignedPayload().getPayload().getBlock();
}
}

@ -24,10 +24,10 @@ import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Prepare;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Proposal;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.RoundChange;
import tech.pegasys.pantheon.consensus.ibft.payload.MessageFactory;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparedCertificate;
import tech.pegasys.pantheon.consensus.ibft.payload.ProposalPayload;
import tech.pegasys.pantheon.consensus.ibft.payload.RoundChangeCertificate;
import tech.pegasys.pantheon.consensus.ibft.payload.SignedData;
import tech.pegasys.pantheon.consensus.ibft.statemachine.TerminatedRoundArtefacts;
import tech.pegasys.pantheon.crypto.SECP256K1.Signature;
import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.Hash;
@ -75,10 +75,10 @@ public class IbftMessageTransmitter {
public void multicastRoundChange(
final ConsensusRoundIdentifier roundIdentifier,
final Optional<PreparedCertificate> preparedCertificate) {
final Optional<TerminatedRoundArtefacts> terminatedRoundArtefacts) {
final RoundChange data =
messageFactory.createSignedRoundChangePayload(roundIdentifier, preparedCertificate);
messageFactory.createSignedRoundChangePayload(roundIdentifier, terminatedRoundArtefacts);
final RoundChangeMessageData message = RoundChangeMessageData.create(data);

@ -18,6 +18,7 @@ import tech.pegasys.pantheon.consensus.ibft.messagewrappers.NewRound;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Prepare;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Proposal;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.RoundChange;
import tech.pegasys.pantheon.consensus.ibft.statemachine.TerminatedRoundArtefacts;
import tech.pegasys.pantheon.crypto.SECP256K1;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.crypto.SECP256K1.Signature;
@ -64,9 +65,12 @@ public class MessageFactory {
public RoundChange createSignedRoundChangePayload(
final ConsensusRoundIdentifier roundIdentifier,
final Optional<PreparedCertificate> preparedCertificate) {
final Optional<TerminatedRoundArtefacts> terminatedRoundArtefacts) {
final RoundChangePayload payload = new RoundChangePayload(roundIdentifier, preparedCertificate);
final RoundChangePayload payload =
new RoundChangePayload(
roundIdentifier,
terminatedRoundArtefacts.map(TerminatedRoundArtefacts::getPreparedCertificate));
return new RoundChange(createSignedMessage(payload));
}

@ -29,7 +29,6 @@ import tech.pegasys.pantheon.consensus.ibft.messagewrappers.RoundChange;
import tech.pegasys.pantheon.consensus.ibft.network.IbftMessageTransmitter;
import tech.pegasys.pantheon.consensus.ibft.payload.MessageFactory;
import tech.pegasys.pantheon.consensus.ibft.payload.Payload;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparedCertificate;
import tech.pegasys.pantheon.consensus.ibft.payload.RoundChangeCertificate;
import tech.pegasys.pantheon.consensus.ibft.validation.MessageValidatorFactory;
import tech.pegasys.pantheon.consensus.ibft.validation.NewRoundMessageValidator;
@ -70,7 +69,7 @@ public class IbftBlockHeightManager implements BlockHeightManager {
private final Function<ConsensusRoundIdentifier, RoundState> roundStateCreator;
private final IbftFinalState finalState;
private Optional<PreparedCertificate> latestPreparedCertificate = Optional.empty();
private Optional<TerminatedRoundArtefacts> latesteTerminatedRoundArtefacts = Optional.empty();
private IbftRound currentRound;
@ -134,19 +133,20 @@ public class IbftBlockHeightManager implements BlockHeightManager {
LOG.info(
"Round has expired, creating PreparedCertificate and notifying peers. round={}",
currentRound.getRoundIdentifier());
final Optional<PreparedCertificate> preparedCertificate =
currentRound.createPrepareCertificate();
final Optional<TerminatedRoundArtefacts> terminatedRoundArtefats =
currentRound.constructTerminatedRoundArtefacts();
if (preparedCertificate.isPresent()) {
latestPreparedCertificate = preparedCertificate;
if (terminatedRoundArtefats.isPresent()) {
latesteTerminatedRoundArtefacts = terminatedRoundArtefats;
}
startNewRound(currentRound.getRoundIdentifier().getRoundNumber() + 1);
final RoundChange localRoundChange =
messageFactory.createSignedRoundChangePayload(
currentRound.getRoundIdentifier(), latestPreparedCertificate);
transmitter.multicastRoundChange(currentRound.getRoundIdentifier(), latestPreparedCertificate);
currentRound.getRoundIdentifier(), latesteTerminatedRoundArtefacts);
transmitter.multicastRoundChange(
currentRound.getRoundIdentifier(), latesteTerminatedRoundArtefacts);
// Its possible the locally created RoundChange triggers the transmission of a NewRound
// message - so it must be handled accordingly.

@ -189,8 +189,8 @@ public class IbftRound {
peerIsCommitted(msg);
}
public Optional<PreparedCertificate> createPrepareCertificate() {
return roundState.constructPreparedCertificate();
public Optional<TerminatedRoundArtefacts> constructTerminatedRoundArtefacts() {
return roundState.constructTerminatedRoundArtefacts();
}
private boolean updateStateWithProposedBlock(final Proposal msg) {

@ -18,7 +18,6 @@ import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Commit;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Prepare;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Proposal;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparedCertificate;
import tech.pegasys.pantheon.consensus.ibft.validation.MessageValidator;
import tech.pegasys.pantheon.crypto.SECP256K1.Signature;
import tech.pegasys.pantheon.ethereum.core.Block;
@ -44,8 +43,8 @@ public class RoundState {
// Must track the actual Prepare message, not just the sender, as these may need to be reused
// to send out in a PrepareCertificate.
private final Set<Prepare> preparePayloads = Sets.newLinkedHashSet();
private final Set<Commit> commitPayloads = Sets.newLinkedHashSet();
private final Set<Prepare> prepareMessages = Sets.newLinkedHashSet();
private final Set<Commit> commitMessages = Sets.newLinkedHashSet();
private boolean prepared = false;
private boolean committed = false;
@ -68,8 +67,8 @@ public class RoundState {
if (!proposalMessage.isPresent()) {
if (validator.addSignedProposalPayload(msg)) {
proposalMessage = Optional.of(msg);
preparePayloads.removeIf(p -> !validator.validatePrepareMessage(p));
commitPayloads.removeIf(p -> !validator.validateCommitMessage(p));
prepareMessages.removeIf(p -> !validator.validatePrepareMessage(p));
commitMessages.removeIf(p -> !validator.validateCommitMessage(p));
updateState();
return true;
}
@ -80,7 +79,7 @@ public class RoundState {
public void addPrepareMessage(final Prepare msg) {
if (!proposalMessage.isPresent() || validator.validatePrepareMessage(msg)) {
preparePayloads.add(msg);
prepareMessages.add(msg);
LOG.debug("Round state added prepare message prepare={}", msg);
}
updateState();
@ -88,7 +87,7 @@ public class RoundState {
public void addCommitMessage(final Commit msg) {
if (!proposalMessage.isPresent() || validator.validateCommitMessage(msg)) {
commitPayloads.add(msg);
commitMessages.add(msg);
LOG.debug("Round state added commit message commit={}", msg);
}
@ -99,8 +98,8 @@ public class RoundState {
// NOTE: The quorum for Prepare messages is 1 less than the quorum size as the proposer
// does not supply a prepare message
final long prepareQuorum = prepareMessageCountForQuorum(quorum);
prepared = (preparePayloads.size() >= prepareQuorum) && proposalMessage.isPresent();
committed = (commitPayloads.size() >= quorum) && proposalMessage.isPresent();
prepared = (prepareMessages.size() >= prepareQuorum) && proposalMessage.isPresent();
committed = (commitMessages.size() >= quorum) && proposalMessage.isPresent();
LOG.debug(
"Round state updated prepared={} committed={} prepareQuorum={} quorum={}",
prepared,
@ -122,21 +121,15 @@ public class RoundState {
}
public Collection<Signature> getCommitSeals() {
return commitPayloads
return commitMessages
.stream()
.map(cp -> cp.getSignedPayload().getPayload().getCommitSeal())
.collect(Collectors.toList());
}
public Optional<PreparedCertificate> constructPreparedCertificate() {
public Optional<TerminatedRoundArtefacts> constructTerminatedRoundArtefacts() {
if (isPrepared()) {
return Optional.of(
new PreparedCertificate(
proposalMessage.get().getSignedPayload(),
preparePayloads
.stream()
.map(Prepare::getSignedPayload)
.collect(Collectors.toList())));
return Optional.of(new TerminatedRoundArtefacts(proposalMessage.get(), prepareMessages));
}
return Optional.empty();
}

@ -0,0 +1,42 @@
/*
* 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.messagewrappers.Prepare;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Proposal;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparedCertificate;
import tech.pegasys.pantheon.ethereum.core.Block;
import java.util.Collection;
import java.util.stream.Collectors;
public class TerminatedRoundArtefacts {
private Proposal proposal;
private Collection<Prepare> prepares;
public TerminatedRoundArtefacts(final Proposal proposal, final Collection<Prepare> prepares) {
this.proposal = proposal;
this.prepares = prepares;
}
public Block getBlock() {
return proposal.getBlock();
}
public PreparedCertificate getPreparedCertificate() {
return new PreparedCertificate(
proposal.getSignedPayload(),
prepares.stream().map(Prepare::getSignedPayload).collect(Collectors.toList()));
}
}

@ -20,6 +20,7 @@ import static tech.pegasys.pantheon.consensus.ibft.IbftHelpers.calculateRequired
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Proposal;
import tech.pegasys.pantheon.consensus.ibft.payload.MessageFactory;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparedCertificate;
import tech.pegasys.pantheon.consensus.ibft.statemachine.TerminatedRoundArtefacts;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.Hash;
@ -92,17 +93,15 @@ public class IbftHelpersTest {
final Proposal differentProposal =
proposerMessageFactory.createSignedProposalPayload(preparedRound, proposedBlock);
final Optional<PreparedCertificate> latterPreparedCert =
final Optional<TerminatedRoundArtefacts> latterTerminatedRoundArtefacts =
Optional.of(
new PreparedCertificate(
differentProposal.getSignedPayload(),
new TerminatedRoundArtefacts(
differentProposal,
Lists.newArrayList(
proposerMessageFactory
.createSignedPreparePayload(roundIdentifier, proposedBlock.getHash())
.getSignedPayload(),
proposerMessageFactory
.createSignedPreparePayload(roundIdentifier, proposedBlock.getHash())
.getSignedPayload())));
proposerMessageFactory.createSignedPreparePayload(
roundIdentifier, proposedBlock.getHash()),
proposerMessageFactory.createSignedPreparePayload(
roundIdentifier, proposedBlock.getHash()))));
// An earlier PrepareCert is added to ensure the path to find the latest PrepareCert
// is correctly followed.
@ -110,29 +109,29 @@ public class IbftHelpersTest {
TestHelpers.createFrom(roundIdentifier, 0, -2);
final Proposal earlierProposal =
proposerMessageFactory.createSignedProposalPayload(earlierPreparedRound, proposedBlock);
final Optional<PreparedCertificate> earlierPreparedCert =
final Optional<TerminatedRoundArtefacts> earlierTerminatedRoundArtefacts =
Optional.of(
new PreparedCertificate(
earlierProposal.getSignedPayload(),
new TerminatedRoundArtefacts(
earlierProposal,
Lists.newArrayList(
proposerMessageFactory
.createSignedPreparePayload(earlierPreparedRound, proposedBlock.getHash())
.getSignedPayload(),
proposerMessageFactory
.createSignedPreparePayload(earlierPreparedRound, proposedBlock.getHash())
.getSignedPayload())));
proposerMessageFactory.createSignedPreparePayload(
earlierPreparedRound, proposedBlock.getHash()),
proposerMessageFactory.createSignedPreparePayload(
earlierPreparedRound, proposedBlock.getHash()))));
final Optional<PreparedCertificate> newestCert =
IbftHelpers.findLatestPreparedCertificate(
Lists.newArrayList(
proposerMessageFactory
.createSignedRoundChangePayload(roundIdentifier, earlierPreparedCert)
.createSignedRoundChangePayload(
roundIdentifier, earlierTerminatedRoundArtefacts)
.getSignedPayload(),
proposerMessageFactory
.createSignedRoundChangePayload(roundIdentifier, latterPreparedCert)
.createSignedRoundChangePayload(roundIdentifier, latterTerminatedRoundArtefacts)
.getSignedPayload()));
assertThat(newestCert).isEqualTo(latterPreparedCert);
assertThat(newestCert.get())
.isEqualTo(latterTerminatedRoundArtefacts.get().getPreparedCertificate());
}
@Test

@ -40,7 +40,6 @@ import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Prepare;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.RoundChange;
import tech.pegasys.pantheon.consensus.ibft.network.IbftMessageTransmitter;
import tech.pegasys.pantheon.consensus.ibft.payload.MessageFactory;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparedCertificate;
import tech.pegasys.pantheon.consensus.ibft.payload.RoundChangeCertificate;
import tech.pegasys.pantheon.consensus.ibft.validation.MessageValidator;
import tech.pegasys.pantheon.consensus.ibft.validation.MessageValidatorFactory;
@ -93,7 +92,7 @@ public class IbftBlockHeightManagerTest {
@Mock private RoundTimer roundTimer;
@Mock private NewRoundMessageValidator newRoundMessageValidator;
@Captor private ArgumentCaptor<Optional<PreparedCertificate>> preparedCaptor;
@Captor private ArgumentCaptor<Optional<TerminatedRoundArtefacts>> terminatedRoundArtefactsCaptor;
private final List<KeyPair> validatorKeys = Lists.newArrayList();
private final List<Address> validators = Lists.newArrayList();
@ -360,12 +359,13 @@ public class IbftBlockHeightManagerTest {
final ConsensusRoundIdentifier nextRound = createFrom(roundIdentifier, 0, +1);
verify(messageTransmitter, times(1))
.multicastRoundChange(eq(nextRound), preparedCaptor.capture());
final Optional<PreparedCertificate> preparedCert = preparedCaptor.getValue();
.multicastRoundChange(eq(nextRound), terminatedRoundArtefactsCaptor.capture());
final Optional<TerminatedRoundArtefacts> preparedCert =
terminatedRoundArtefactsCaptor.getValue();
assertThat(preparedCert).isNotEmpty();
assertThat(preparedCert.get().getPreparePayloads())
assertThat(preparedCert.get().getPreparedCertificate().getPreparePayloads())
.containsOnly(firstPrepare.getSignedPayload(), secondPrepare.getSignedPayload());
}
}

@ -30,7 +30,6 @@ import tech.pegasys.pantheon.consensus.ibft.IbftExtraData;
import tech.pegasys.pantheon.consensus.ibft.blockcreation.IbftBlockCreator;
import tech.pegasys.pantheon.consensus.ibft.network.IbftMessageTransmitter;
import tech.pegasys.pantheon.consensus.ibft.payload.MessageFactory;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparedCertificate;
import tech.pegasys.pantheon.consensus.ibft.payload.ProposalPayload;
import tech.pegasys.pantheon.consensus.ibft.payload.RoundChangeCertificate;
import tech.pegasys.pantheon.consensus.ibft.payload.SignedData;
@ -305,10 +304,9 @@ public class IbftRoundTest {
.createSignedRoundChangePayload(
roundIdentifier,
Optional.of(
new PreparedCertificate(
messageFactory
.createSignedProposalPayload(priorRoundChange, proposedBlock)
.getSignedPayload(),
new TerminatedRoundArtefacts(
messageFactory.createSignedProposalPayload(
priorRoundChange, proposedBlock),
Collections.emptyList())))
.getSignedPayload()));
// NOTE: IbftRound assumes the prepare's are valid

@ -21,12 +21,10 @@ import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibft.IbftContext;
import tech.pegasys.pantheon.consensus.ibft.IbftHelpers;
import tech.pegasys.pantheon.consensus.ibft.TestHelpers;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Prepare;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Proposal;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.RoundChange;
import tech.pegasys.pantheon.consensus.ibft.payload.MessageFactory;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparePayload;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparedCertificate;
import tech.pegasys.pantheon.consensus.ibft.payload.SignedData;
import tech.pegasys.pantheon.consensus.ibft.validation.RoundChangeMessageValidator;
import tech.pegasys.pantheon.consensus.ibft.validation.SignedDataValidator;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
@ -142,22 +140,21 @@ public class RoundChangeManagerTest {
// Proposal must come from an earlier round.
final Proposal proposal = messageFactory.createSignedProposalPayload(proposalRound, block);
final List<SignedData<PreparePayload>> preparePayloads =
final List<Prepare> preparePayloads =
prepareProviders
.stream()
.map(
k -> {
final MessageFactory prepareFactory = new MessageFactory(k);
return prepareFactory
.createSignedPreparePayload(proposalRound, block.getHash())
.getSignedPayload();
return prepareFactory.createSignedPreparePayload(proposalRound, block.getHash());
})
.collect(Collectors.toList());
final PreparedCertificate cert =
new PreparedCertificate(proposal.getSignedPayload(), preparePayloads);
final TerminatedRoundArtefacts terminatedRoundArtects =
new TerminatedRoundArtefacts(proposal, preparePayloads);
return messageFactory.createSignedRoundChangePayload(round, Optional.of(cert));
return messageFactory.createSignedRoundChangePayload(
round, Optional.of(terminatedRoundArtects));
}
@Test

@ -71,7 +71,7 @@ public class RoundStateTest {
assertThat(roundState.isPrepared()).isFalse();
assertThat(roundState.isCommitted()).isFalse();
assertThat(roundState.constructPreparedCertificate()).isEmpty();
assertThat(roundState.constructTerminatedRoundArtefacts()).isEmpty();
}
@Test
@ -85,7 +85,7 @@ public class RoundStateTest {
assertThat(roundState.setProposedBlock(proposal)).isFalse();
assertThat(roundState.isPrepared()).isFalse();
assertThat(roundState.isCommitted()).isFalse();
assertThat(roundState.constructPreparedCertificate()).isEmpty();
assertThat(roundState.constructTerminatedRoundArtefacts()).isEmpty();
}
@Test
@ -99,8 +99,13 @@ public class RoundStateTest {
assertThat(roundState.setProposedBlock(proposal)).isTrue();
assertThat(roundState.isPrepared()).isTrue();
assertThat(roundState.isCommitted()).isFalse();
assertThat(roundState.constructPreparedCertificate()).isNotEmpty();
assertThat(roundState.constructPreparedCertificate().get().getProposalPayload())
assertThat(roundState.constructTerminatedRoundArtefacts()).isNotEmpty();
assertThat(
roundState
.constructTerminatedRoundArtefacts()
.get()
.getPreparedCertificate()
.getProposalPayload())
.isEqualTo(proposal.getSignedPayload());
}
@ -129,7 +134,7 @@ public class RoundStateTest {
roundState.addCommitMessage(commit);
assertThat(roundState.isPrepared()).isTrue();
assertThat(roundState.isCommitted()).isTrue();
assertThat(roundState.constructPreparedCertificate()).isNotEmpty();
assertThat(roundState.constructTerminatedRoundArtefacts()).isNotEmpty();
}
@Test
@ -152,19 +157,19 @@ public class RoundStateTest {
roundState.addPrepareMessage(firstPrepare);
assertThat(roundState.isPrepared()).isFalse();
assertThat(roundState.isCommitted()).isFalse();
assertThat(roundState.constructPreparedCertificate()).isEmpty();
assertThat(roundState.constructTerminatedRoundArtefacts()).isEmpty();
roundState.addPrepareMessage(secondPrepare);
assertThat(roundState.isPrepared()).isFalse();
assertThat(roundState.isCommitted()).isFalse();
assertThat(roundState.constructPreparedCertificate()).isEmpty();
assertThat(roundState.constructTerminatedRoundArtefacts()).isEmpty();
final Proposal proposal =
validatorMessageFactories.get(0).createSignedProposalPayload(roundIdentifier, block);
assertThat(roundState.setProposedBlock(proposal)).isTrue();
assertThat(roundState.isPrepared()).isTrue();
assertThat(roundState.isCommitted()).isFalse();
assertThat(roundState.constructPreparedCertificate()).isNotEmpty();
assertThat(roundState.constructTerminatedRoundArtefacts()).isNotEmpty();
}
@Test
@ -197,7 +202,7 @@ public class RoundStateTest {
assertThat(roundState.setProposedBlock(proposal)).isTrue();
assertThat(roundState.isPrepared()).isFalse();
assertThat(roundState.isCommitted()).isFalse();
assertThat(roundState.constructPreparedCertificate()).isEmpty();
assertThat(roundState.constructTerminatedRoundArtefacts()).isEmpty();
}
@Test

@ -25,8 +25,8 @@ import tech.pegasys.pantheon.consensus.ibft.messagewrappers.NewRound;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Proposal;
import tech.pegasys.pantheon.consensus.ibft.payload.MessageFactory;
import tech.pegasys.pantheon.consensus.ibft.payload.NewRoundPayload;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparedCertificate;
import tech.pegasys.pantheon.consensus.ibft.payload.RoundChangeCertificate;
import tech.pegasys.pantheon.consensus.ibft.statemachine.TerminatedRoundArtefacts;
import tech.pegasys.pantheon.consensus.ibft.validation.RoundChangeMessageValidator.MessageValidatorForHeightFactory;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.core.Address;
@ -165,22 +165,19 @@ public class NewRoundSignedDataValidatorTest {
final Block prevProposedBlock =
TestHelpers.createProposalBlock(validators.subList(0, 1), roundIdentifier.getRoundNumber());
final PreparedCertificate misMatchedPreparedCertificate =
new PreparedCertificate(
proposerMessageFactory
.createSignedProposalPayload(preparedRound, prevProposedBlock)
.getSignedPayload(),
final TerminatedRoundArtefacts mismatchedRoundArtefacts =
new TerminatedRoundArtefacts(
proposerMessageFactory.createSignedProposalPayload(preparedRound, prevProposedBlock),
singletonList(
validatorMessageFactory
.createSignedPreparePayload(preparedRound, prevProposedBlock.getHash())
.getSignedPayload()));
validatorMessageFactory.createSignedPreparePayload(
preparedRound, prevProposedBlock.getHash())));
msgBuilder.setRoundChangeCertificate(
new RoundChangeCertificate(
singletonList(
validatorMessageFactory
.createSignedRoundChangePayload(
roundIdentifier, Optional.of(misMatchedPreparedCertificate))
roundIdentifier, Optional.of(mismatchedRoundArtefacts))
.getSignedPayload())));
final NewRound invalidMsg = signPayload(msgBuilder.build(), proposerKey);
@ -214,14 +211,11 @@ public class NewRoundSignedDataValidatorTest {
proposerMessageFactory.createSignedRoundChangePayload(
roundIdentifier,
Optional.of(
new PreparedCertificate(
proposerMessageFactory
.createSignedProposalPayload(prevRound, proposedBlock)
.getSignedPayload(),
new TerminatedRoundArtefacts(
proposerMessageFactory.createSignedProposalPayload(prevRound, proposedBlock),
Lists.newArrayList(
validatorMessageFactory
.createSignedPreparePayload(prevRound, proposedBlock.getHash())
.getSignedPayload())))));
validatorMessageFactory.createSignedPreparePayload(
prevRound, proposedBlock.getHash()))))));
msgBuilder.setRoundChangeCertificate(roundChangeBuilder.buildCertificate());
@ -240,14 +234,13 @@ public class NewRoundSignedDataValidatorTest {
roundIdentifier.getSequenceNumber(), roundIdentifier.getRoundNumber() - 1);
final Proposal latterProposal =
proposerMessageFactory.createSignedProposalPayload(latterPrepareRound, proposedBlock);
final Optional<PreparedCertificate> preparedCert =
final Optional<TerminatedRoundArtefacts> preparedCert =
Optional.of(
new PreparedCertificate(
latterProposal.getSignedPayload(),
new TerminatedRoundArtefacts(
latterProposal,
Lists.newArrayList(
validatorMessageFactory
.createSignedPreparePayload(roundIdentifier, proposedBlock.getHash())
.getSignedPayload())));
validatorMessageFactory.createSignedPreparePayload(
roundIdentifier, proposedBlock.getHash()))));
// An earlier PrepareCert is added to ensure the path to find the latest PrepareCert
// is correctly followed.
@ -258,14 +251,13 @@ public class NewRoundSignedDataValidatorTest {
roundIdentifier.getSequenceNumber(), roundIdentifier.getRoundNumber() - 2);
final Proposal earlierProposal =
proposerMessageFactory.createSignedProposalPayload(earlierPreparedRound, earlierBlock);
final Optional<PreparedCertificate> earlierPreparedCert =
final Optional<TerminatedRoundArtefacts> earlierPreparedCert =
Optional.of(
new PreparedCertificate(
earlierProposal.getSignedPayload(),
new TerminatedRoundArtefacts(
earlierProposal,
Lists.newArrayList(
validatorMessageFactory
.createSignedPreparePayload(earlierPreparedRound, earlierBlock.getHash())
.getSignedPayload())));
validatorMessageFactory.createSignedPreparePayload(
earlierPreparedRound, earlierBlock.getHash()))));
final RoundChangeCertificate roundChangeCert =
new RoundChangeCertificate(

@ -25,6 +25,7 @@ import tech.pegasys.pantheon.consensus.ibft.messagewrappers.Prepare;
import tech.pegasys.pantheon.consensus.ibft.messagewrappers.RoundChange;
import tech.pegasys.pantheon.consensus.ibft.payload.MessageFactory;
import tech.pegasys.pantheon.consensus.ibft.payload.PreparedCertificate;
import tech.pegasys.pantheon.consensus.ibft.statemachine.TerminatedRoundArtefacts;
import tech.pegasys.pantheon.consensus.ibft.validation.RoundChangeMessageValidator.MessageValidatorForHeightFactory;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.core.Address;
@ -95,16 +96,17 @@ public class RoundChangeSignedDataValidatorTest {
@Test
public void roundChangeContainingInvalidProposalFails() {
final PreparedCertificate prepareCertificate =
new PreparedCertificate(
proposerMessageFactory
.createSignedProposalPayload(currentRound, block)
.getSignedPayload(),
final TerminatedRoundArtefacts terminatedRoundArtefacts =
new TerminatedRoundArtefacts(
proposerMessageFactory.createSignedProposalPayload(currentRound, block),
Collections.emptyList());
final PreparedCertificate prepareCertificate =
terminatedRoundArtefacts.getPreparedCertificate();
final RoundChange msg =
proposerMessageFactory.createSignedRoundChangePayload(
targetRound, Optional.of(prepareCertificate));
targetRound, Optional.of(terminatedRoundArtefacts));
when(basicValidator.addSignedProposalPayload(any())).thenReturn(false);
@ -119,16 +121,14 @@ public class RoundChangeSignedDataValidatorTest {
@Test
public void roundChangeContainingValidProposalButNoPrepareMessagesFails() {
final PreparedCertificate prepareCertificate =
new PreparedCertificate(
proposerMessageFactory
.createSignedProposalPayload(currentRound, block)
.getSignedPayload(),
final TerminatedRoundArtefacts terminatedRoundArtefacts =
new TerminatedRoundArtefacts(
proposerMessageFactory.createSignedProposalPayload(currentRound, block),
Collections.emptyList());
final RoundChange msg =
proposerMessageFactory.createSignedRoundChangePayload(
targetRound, Optional.of(prepareCertificate));
targetRound, Optional.of(terminatedRoundArtefacts));
when(basicValidator.addSignedProposalPayload(any())).thenReturn(true);
assertThat(validator.validateMessage(msg.getSignedPayload())).isFalse();
@ -138,19 +138,17 @@ public class RoundChangeSignedDataValidatorTest {
public void roundChangeInvalidPrepareMessageFromProposerFails() {
final Prepare prepareMsg =
validatorMessageFactory.createSignedPreparePayload(currentRound, block.getHash());
final PreparedCertificate prepareCertificate =
new PreparedCertificate(
proposerMessageFactory
.createSignedProposalPayload(currentRound, block)
.getSignedPayload(),
Lists.newArrayList(prepareMsg.getSignedPayload()));
final TerminatedRoundArtefacts terminatedRoundArtefacts =
new TerminatedRoundArtefacts(
proposerMessageFactory.createSignedProposalPayload(currentRound, block),
Lists.newArrayList(prepareMsg));
when(basicValidator.addSignedProposalPayload(any())).thenReturn(true);
when(basicValidator.validatePrepareMessage(any())).thenReturn(false);
final RoundChange msg =
proposerMessageFactory.createSignedRoundChangePayload(
targetRound, Optional.of(prepareCertificate));
targetRound, Optional.of(terminatedRoundArtefacts));
assertThat(validator.validateMessage(msg.getSignedPayload())).isFalse();
@ -179,16 +177,14 @@ public class RoundChangeSignedDataValidatorTest {
final Prepare prepareMsg =
validatorMessageFactory.createSignedPreparePayload(futureRound, block.getHash());
final PreparedCertificate prepareCertificate =
new PreparedCertificate(
proposerMessageFactory
.createSignedProposalPayload(futureRound, block)
.getSignedPayload(),
Lists.newArrayList(prepareMsg.getSignedPayload()));
final TerminatedRoundArtefacts terminatedRoundArtefacts =
new TerminatedRoundArtefacts(
proposerMessageFactory.createSignedProposalPayload(futureRound, block),
Lists.newArrayList(prepareMsg));
final RoundChange msg =
proposerMessageFactory.createSignedRoundChangePayload(
targetRound, Optional.of(prepareCertificate));
targetRound, Optional.of(terminatedRoundArtefacts));
assertThat(validator.validateMessage(msg.getSignedPayload())).isFalse();
verify(validatorFactory, never()).createAt(any());
@ -200,16 +196,17 @@ public class RoundChangeSignedDataValidatorTest {
public void roundChangeWithPastProposalForCurrentHeightIsSuccessful() {
final Prepare prepareMsg =
validatorMessageFactory.createSignedPreparePayload(currentRound, block.getHash());
final TerminatedRoundArtefacts terminatedRoundArtefacts =
new TerminatedRoundArtefacts(
proposerMessageFactory.createSignedProposalPayload(currentRound, block),
Lists.newArrayList(prepareMsg));
final PreparedCertificate prepareCertificate =
new PreparedCertificate(
proposerMessageFactory
.createSignedProposalPayload(currentRound, block)
.getSignedPayload(),
Lists.newArrayList(prepareMsg.getSignedPayload()));
terminatedRoundArtefacts.getPreparedCertificate();
final RoundChange msg =
proposerMessageFactory.createSignedRoundChangePayload(
targetRound, Optional.of(prepareCertificate));
targetRound, Optional.of(terminatedRoundArtefacts));
when(basicValidator.addSignedProposalPayload(prepareCertificate.getProposalPayload()))
.thenReturn(true);

Loading…
Cancel
Save