Renamed IBFT message classes (#333)

The classes used around the IBFT Messaging classes have all been renamed to make their use less cumbersome throughout the codebase.

Other issues are yet to be found (not all variable names and function names have been captured in this sweep).
tmohay 6 years ago committed by GitHub
parent d9a7ad2eb8
commit 7891132dd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 26
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftMessages.java
  2. 2
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/ProposerSelector.java
  3. 4
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/AbstractIbftMessage.java
  4. 21
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/CommitMessage.java
  5. 49
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/IbftPrePrepareMessage.java
  6. 2
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/IbftV2.java
  7. 21
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/NewRoundMessage.java
  8. 21
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/PrepareMessage.java
  9. 47
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/ProposalMessage.java
  10. 22
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/RoundChangeMessage.java
  11. 2
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/AbstractPayload.java
  12. 8
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/CommitPayload.java
  13. 108
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/IbftMessageFactory.java
  14. 62
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/IbftPreparedCertificate.java
  15. 53
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/IbftRoundChangeCertificate.java
  16. 5
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/InRoundPayload.java
  17. 98
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/MessageFactory.java
  18. 34
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/NewRoundPayload.java
  19. 9
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/PreparePayload.java
  20. 58
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/PreparedCertificate.java
  21. 13
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/ProposalPayload.java
  22. 48
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/RoundChangeCertificate.java
  23. 18
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/RoundChangePayload.java
  24. 55
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/SignedData.java
  25. 2
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/protocol/IbftSubProtocol.java
  26. 101
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/validation/MessageValidator.java
  27. 53
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/validation/RoundChangeMessageValidator.java
  28. 153
      consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/validation/MessageValidatorTest.java
  29. 119
      consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/validation/RoundChangeMessageValidatorTest.java

@ -12,36 +12,36 @@
*/ */
package tech.pegasys.pantheon.consensus.ibft; package tech.pegasys.pantheon.consensus.ibft;
import tech.pegasys.pantheon.consensus.ibft.ibftmessage.IbftCommitMessage; import tech.pegasys.pantheon.consensus.ibft.ibftmessage.CommitMessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessage.IbftNewRoundMessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessage.IbftPrePrepareMessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessage.IbftPrepareMessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessage.IbftRoundChangeMessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessage.IbftV2; import tech.pegasys.pantheon.consensus.ibft.ibftmessage.IbftV2;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftSignedMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessage.NewRoundMessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessage.PrepareMessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessage.ProposalMessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessage.RoundChangeMessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.SignedData;
import tech.pegasys.pantheon.ethereum.p2p.api.Message; import tech.pegasys.pantheon.ethereum.p2p.api.Message;
import tech.pegasys.pantheon.ethereum.p2p.api.MessageData; import tech.pegasys.pantheon.ethereum.p2p.api.MessageData;
public class IbftMessages { public class IbftMessages {
public static IbftSignedMessageData<?> fromMessage(final Message message) { public static SignedData<?> fromMessage(final Message message) {
final MessageData messageData = message.getData(); final MessageData messageData = message.getData();
switch (messageData.getCode()) { switch (messageData.getCode()) {
case IbftV2.PRE_PREPARE: case IbftV2.PROPOSAL:
return IbftPrePrepareMessage.fromMessage(messageData).decode(); return ProposalMessage.fromMessage(messageData).decode();
case IbftV2.PREPARE: case IbftV2.PREPARE:
return IbftPrepareMessage.fromMessage(messageData).decode(); return PrepareMessage.fromMessage(messageData).decode();
case IbftV2.COMMIT: case IbftV2.COMMIT:
return IbftCommitMessage.fromMessage(messageData).decode(); return CommitMessage.fromMessage(messageData).decode();
case IbftV2.ROUND_CHANGE: case IbftV2.ROUND_CHANGE:
return IbftRoundChangeMessage.fromMessage(messageData).decode(); return RoundChangeMessage.fromMessage(messageData).decode();
case IbftV2.NEW_ROUND: case IbftV2.NEW_ROUND:
return IbftNewRoundMessage.fromMessage(messageData).decode(); return NewRoundMessage.fromMessage(messageData).decode();
default: default:
throw new IllegalArgumentException( throw new IllegalArgumentException(

@ -33,7 +33,7 @@ import org.apache.logging.log4j.Logger;
/** /**
* Responsible for determining which member of the validator pool should propose the next block * Responsible for determining which member of the validator pool should propose the next block
* (i.e. send the Preprepare message). * (i.e. send the Proposal message).
* *
* <p>It does this by extracting the previous block's proposer from the ProposerSeal (stored in the * <p>It does this by extracting the previous block's proposer from the ProposerSeal (stored in the
* Blocks ExtraData) then iterating through the validator list (stored in {@link * Blocks ExtraData) then iterating through the validator list (stored in {@link

@ -12,7 +12,7 @@
*/ */
package tech.pegasys.pantheon.consensus.ibft.ibftmessage; package tech.pegasys.pantheon.consensus.ibft.ibftmessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftSignedMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.SignedData;
import tech.pegasys.pantheon.ethereum.p2p.api.MessageData; import tech.pegasys.pantheon.ethereum.p2p.api.MessageData;
import tech.pegasys.pantheon.ethereum.p2p.wire.AbstractMessageData; import tech.pegasys.pantheon.ethereum.p2p.wire.AbstractMessageData;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
@ -24,7 +24,7 @@ public abstract class AbstractIbftMessage extends AbstractMessageData {
super(data); super(data);
} }
public abstract IbftSignedMessageData<?> decode(); public abstract SignedData<?> decode();
protected static <T extends AbstractIbftMessage> T fromMessage( protected static <T extends AbstractIbftMessage> T fromMessage(
final MessageData message, final MessageData message,

@ -12,33 +12,32 @@
*/ */
package tech.pegasys.pantheon.consensus.ibft.ibftmessage; package tech.pegasys.pantheon.consensus.ibft.ibftmessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftSignedMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.CommitPayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftUnsignedCommitMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.SignedData;
import tech.pegasys.pantheon.ethereum.p2p.api.MessageData; import tech.pegasys.pantheon.ethereum.p2p.api.MessageData;
import tech.pegasys.pantheon.ethereum.rlp.RLP; import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
public class IbftCommitMessage extends AbstractIbftMessage { public class CommitMessage extends AbstractIbftMessage {
private static final int MESSAGE_CODE = IbftV2.COMMIT; private static final int MESSAGE_CODE = IbftV2.COMMIT;
private IbftCommitMessage(final BytesValue data) { private CommitMessage(final BytesValue data) {
super(data); super(data);
} }
public static IbftCommitMessage fromMessage(final MessageData message) { public static CommitMessage fromMessage(final MessageData message) {
return fromMessage(message, MESSAGE_CODE, IbftCommitMessage.class, IbftCommitMessage::new); return fromMessage(message, MESSAGE_CODE, CommitMessage.class, CommitMessage::new);
} }
@Override @Override
public IbftSignedMessageData<IbftUnsignedCommitMessageData> decode() { public SignedData<CommitPayload> decode() {
return IbftSignedMessageData.readIbftSignedCommitMessageDataFrom(RLP.input(data)); return SignedData.readSignedCommitPayloadFrom(RLP.input(data));
} }
public static IbftCommitMessage create( public static CommitMessage create(final SignedData<CommitPayload> signedPayload) {
final IbftSignedMessageData<IbftUnsignedCommitMessageData> ibftPrepareMessageDecoded) {
return new IbftCommitMessage(ibftPrepareMessageDecoded.encode()); return new CommitMessage(signedPayload.encode());
} }
@Override @Override

@ -1,49 +0,0 @@
/*
* 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.ibftmessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftSignedMessageData;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftUnsignedPrePrepareMessageData;
import tech.pegasys.pantheon.ethereum.p2p.api.MessageData;
import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.util.bytes.BytesValue;
public class IbftPrePrepareMessage extends AbstractIbftMessage {
private static final int MESSAGE_CODE = IbftV2.PRE_PREPARE;
private IbftPrePrepareMessage(final BytesValue data) {
super(data);
}
public static IbftPrePrepareMessage fromMessage(final MessageData message) {
return fromMessage(
message, MESSAGE_CODE, IbftPrePrepareMessage.class, IbftPrePrepareMessage::new);
}
@Override
public IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> decode() {
return IbftSignedMessageData.readIbftSignedPrePrepareMessageDataFrom(RLP.input(data));
}
public static IbftPrePrepareMessage create(
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> ibftPrepareMessageDecoded) {
return new IbftPrePrepareMessage(ibftPrepareMessageDecoded.encode());
}
@Override
public int getCode() {
return MESSAGE_CODE;
}
}

@ -14,7 +14,7 @@ package tech.pegasys.pantheon.consensus.ibft.ibftmessage;
/** Message codes for iBFT v2 messages */ /** Message codes for iBFT v2 messages */
public class IbftV2 { public class IbftV2 {
public static final int PRE_PREPARE = 0; public static final int PROPOSAL = 0;
public static final int PREPARE = 1; public static final int PREPARE = 1;
public static final int COMMIT = 2; public static final int COMMIT = 2;
public static final int ROUND_CHANGE = 3; public static final int ROUND_CHANGE = 3;

@ -12,33 +12,32 @@
*/ */
package tech.pegasys.pantheon.consensus.ibft.ibftmessage; package tech.pegasys.pantheon.consensus.ibft.ibftmessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftSignedMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.NewRoundPayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftUnsignedNewRoundMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.SignedData;
import tech.pegasys.pantheon.ethereum.p2p.api.MessageData; import tech.pegasys.pantheon.ethereum.p2p.api.MessageData;
import tech.pegasys.pantheon.ethereum.rlp.RLP; import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
public class IbftNewRoundMessage extends AbstractIbftMessage { public class NewRoundMessage extends AbstractIbftMessage {
private static final int MESSAGE_CODE = IbftV2.NEW_ROUND; private static final int MESSAGE_CODE = IbftV2.NEW_ROUND;
private IbftNewRoundMessage(final BytesValue data) { private NewRoundMessage(final BytesValue data) {
super(data); super(data);
} }
public static IbftNewRoundMessage fromMessage(final MessageData message) { public static NewRoundMessage fromMessage(final MessageData message) {
return fromMessage(message, MESSAGE_CODE, IbftNewRoundMessage.class, IbftNewRoundMessage::new); return fromMessage(message, MESSAGE_CODE, NewRoundMessage.class, NewRoundMessage::new);
} }
@Override @Override
public IbftSignedMessageData<IbftUnsignedNewRoundMessageData> decode() { public SignedData<NewRoundPayload> decode() {
return IbftSignedMessageData.readIbftSignedNewRoundMessageDataFrom(RLP.input(data)); return SignedData.readSignedNewRoundPayloadFrom(RLP.input(data));
} }
public static IbftNewRoundMessage create( public static NewRoundMessage create(final SignedData<NewRoundPayload> signedPayload) {
final IbftSignedMessageData<IbftUnsignedNewRoundMessageData> ibftPrepareMessageDecoded) {
return new IbftNewRoundMessage(ibftPrepareMessageDecoded.encode()); return new NewRoundMessage(signedPayload.encode());
} }
@Override @Override

@ -12,33 +12,32 @@
*/ */
package tech.pegasys.pantheon.consensus.ibft.ibftmessage; package tech.pegasys.pantheon.consensus.ibft.ibftmessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftSignedMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.PreparePayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftUnsignedPrepareMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.SignedData;
import tech.pegasys.pantheon.ethereum.p2p.api.MessageData; import tech.pegasys.pantheon.ethereum.p2p.api.MessageData;
import tech.pegasys.pantheon.ethereum.rlp.RLP; import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
public class IbftPrepareMessage extends AbstractIbftMessage { public class PrepareMessage extends AbstractIbftMessage {
private static final int MESSAGE_CODE = IbftV2.PREPARE; private static final int MESSAGE_CODE = IbftV2.PREPARE;
private IbftPrepareMessage(final BytesValue data) { private PrepareMessage(final BytesValue data) {
super(data); super(data);
} }
public static IbftPrepareMessage fromMessage(final MessageData message) { public static PrepareMessage fromMessage(final MessageData message) {
return fromMessage(message, MESSAGE_CODE, IbftPrepareMessage.class, IbftPrepareMessage::new); return fromMessage(message, MESSAGE_CODE, PrepareMessage.class, PrepareMessage::new);
} }
@Override @Override
public IbftSignedMessageData<IbftUnsignedPrepareMessageData> decode() { public SignedData<PreparePayload> decode() {
return IbftSignedMessageData.readIbftSignedPrepareMessageDataFrom(RLP.input(data)); return SignedData.readSignedPreparePayloadFrom(RLP.input(data));
} }
public static IbftPrepareMessage create( public static PrepareMessage create(final SignedData<PreparePayload> signedPayload) {
final IbftSignedMessageData<IbftUnsignedPrepareMessageData> ibftPrepareMessageDecoded) {
return new IbftPrepareMessage(ibftPrepareMessageDecoded.encode()); return new PrepareMessage(signedPayload.encode());
} }
@Override @Override

@ -0,0 +1,47 @@
/*
* 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.ibftmessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.ProposalPayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.SignedData;
import tech.pegasys.pantheon.ethereum.p2p.api.MessageData;
import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.util.bytes.BytesValue;
public class ProposalMessage extends AbstractIbftMessage {
private static final int MESSAGE_CODE = IbftV2.PROPOSAL;
private ProposalMessage(final BytesValue data) {
super(data);
}
public static ProposalMessage fromMessage(final MessageData message) {
return fromMessage(message, MESSAGE_CODE, ProposalMessage.class, ProposalMessage::new);
}
@Override
public SignedData<ProposalPayload> decode() {
return SignedData.readSignedProposalPayloadFrom(RLP.input(data));
}
public static ProposalMessage create(final SignedData<ProposalPayload> signedPayload) {
return new ProposalMessage(signedPayload.encode());
}
@Override
public int getCode() {
return MESSAGE_CODE;
}
}

@ -12,34 +12,32 @@
*/ */
package tech.pegasys.pantheon.consensus.ibft.ibftmessage; package tech.pegasys.pantheon.consensus.ibft.ibftmessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftSignedMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.RoundChangePayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftUnsignedRoundChangeMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.SignedData;
import tech.pegasys.pantheon.ethereum.p2p.api.MessageData; import tech.pegasys.pantheon.ethereum.p2p.api.MessageData;
import tech.pegasys.pantheon.ethereum.rlp.RLP; import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
public class IbftRoundChangeMessage extends AbstractIbftMessage { public class RoundChangeMessage extends AbstractIbftMessage {
private static final int MESSAGE_CODE = IbftV2.ROUND_CHANGE; private static final int MESSAGE_CODE = IbftV2.ROUND_CHANGE;
private IbftRoundChangeMessage(final BytesValue data) { private RoundChangeMessage(final BytesValue data) {
super(data); super(data);
} }
public static IbftRoundChangeMessage fromMessage(final MessageData message) { public static RoundChangeMessage fromMessage(final MessageData message) {
return fromMessage( return fromMessage(message, MESSAGE_CODE, RoundChangeMessage.class, RoundChangeMessage::new);
message, MESSAGE_CODE, IbftRoundChangeMessage.class, IbftRoundChangeMessage::new);
} }
@Override @Override
public IbftSignedMessageData<IbftUnsignedRoundChangeMessageData> decode() { public SignedData<RoundChangePayload> decode() {
return IbftSignedMessageData.readIbftSignedRoundChangeMessageDataFrom(RLP.input(data)); return SignedData.readSignedRoundChangePayloadFrom(RLP.input(data));
} }
public static IbftRoundChangeMessage create( public static RoundChangeMessage create(final SignedData<RoundChangePayload> signedPayload) {
final IbftSignedMessageData<IbftUnsignedRoundChangeMessageData> ibftPrepareMessageDecoded) {
return new IbftRoundChangeMessage(ibftPrepareMessageDecoded.encode()); return new RoundChangeMessage(signedPayload.encode());
} }
@Override @Override

@ -18,7 +18,7 @@ import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLPOutput; import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
public abstract class AbstractIbftUnsignedMessageData { public abstract class AbstractPayload {
public abstract void writeTo(final RLPOutput rlpOutput); public abstract void writeTo(final RLPOutput rlpOutput);

@ -19,12 +19,12 @@ import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.rlp.RLPInput; import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLPOutput; import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
public class IbftUnsignedCommitMessageData extends AbstractIbftUnsignedInRoundMessageData { public class CommitPayload extends InRoundPayload {
private static final int TYPE = IbftV2.COMMIT; private static final int TYPE = IbftV2.COMMIT;
private final Hash digest; private final Hash digest;
private final Signature commitSeal; private final Signature commitSeal;
public IbftUnsignedCommitMessageData( public CommitPayload(
final ConsensusRoundIdentifier roundIdentifier, final ConsensusRoundIdentifier roundIdentifier,
final Hash digest, final Hash digest,
final Signature commitSeal) { final Signature commitSeal) {
@ -33,7 +33,7 @@ public class IbftUnsignedCommitMessageData extends AbstractIbftUnsignedInRoundMe
this.commitSeal = commitSeal; this.commitSeal = commitSeal;
} }
public static IbftUnsignedCommitMessageData readFrom(final RLPInput rlpInput) { public static CommitPayload readFrom(final RLPInput rlpInput) {
rlpInput.enterList(); rlpInput.enterList();
final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundIdentifier.readFrom(rlpInput); final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundIdentifier.readFrom(rlpInput);
@ -41,7 +41,7 @@ public class IbftUnsignedCommitMessageData extends AbstractIbftUnsignedInRoundMe
final Signature commitSeal = rlpInput.readBytesValue(Signature::decode); final Signature commitSeal = rlpInput.readBytesValue(Signature::decode);
rlpInput.leaveList(); rlpInput.leaveList();
return new IbftUnsignedCommitMessageData(roundIdentifier, digest, commitSeal); return new CommitPayload(roundIdentifier, digest, commitSeal);
} }
@Override @Override

@ -1,108 +0,0 @@
/*
* 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.ibftmessagedata;
import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
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 tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.core.Util;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import java.util.Optional;
public class IbftMessageFactory {
private final KeyPair validatorKeyPair;
public IbftMessageFactory(final KeyPair validatorKeyPair) {
this.validatorKeyPair = validatorKeyPair;
}
public IbftSignedMessageData<IbftUnsignedPrePrepareMessageData>
createIbftSignedPrePrepareMessageData(
final ConsensusRoundIdentifier roundIdentifier, final Block block) {
IbftUnsignedPrePrepareMessageData prePrepareUnsignedMessageData =
new IbftUnsignedPrePrepareMessageData(roundIdentifier, block);
return createSignedMessage(prePrepareUnsignedMessageData);
}
public IbftSignedMessageData<IbftUnsignedPrepareMessageData> createIbftSignedPrepareMessageData(
final ConsensusRoundIdentifier roundIdentifier, final Hash digest) {
IbftUnsignedPrepareMessageData prepareUnsignedMessageData =
new IbftUnsignedPrepareMessageData(roundIdentifier, digest);
return createSignedMessage(prepareUnsignedMessageData);
}
public IbftSignedMessageData<IbftUnsignedCommitMessageData> createIbftSignedCommitMessageData(
final ConsensusRoundIdentifier roundIdentifier,
final Hash digest,
final Signature commitSeal) {
IbftUnsignedCommitMessageData commitUnsignedMessageData =
new IbftUnsignedCommitMessageData(roundIdentifier, digest, commitSeal);
return createSignedMessage(commitUnsignedMessageData);
}
public IbftSignedMessageData<IbftUnsignedRoundChangeMessageData>
createIbftSignedRoundChangeMessageData(
final ConsensusRoundIdentifier roundIdentifier,
final Optional<IbftPreparedCertificate> preparedCertificate) {
IbftUnsignedRoundChangeMessageData prepareUnsignedMessageData =
new IbftUnsignedRoundChangeMessageData(roundIdentifier, preparedCertificate);
return createSignedMessage(prepareUnsignedMessageData);
}
public IbftSignedMessageData<IbftUnsignedNewRoundMessageData>
createIbftSignedNewRoundChangeMessageData(
final ConsensusRoundIdentifier roundIdentifier,
final IbftRoundChangeCertificate roundChangeCertificate,
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData>
ibftPrePrepareMessageData) {
IbftUnsignedNewRoundMessageData newRoundUnsignedMessageData =
new IbftUnsignedNewRoundMessageData(
roundIdentifier, roundChangeCertificate, ibftPrePrepareMessageData);
return createSignedMessage(newRoundUnsignedMessageData);
}
private <M extends AbstractIbftUnsignedMessageData> IbftSignedMessageData<M> createSignedMessage(
final M ibftUnsignedMessage) {
final Signature signature = sign(ibftUnsignedMessage, validatorKeyPair);
return new IbftSignedMessageData<>(
ibftUnsignedMessage, Util.publicKeyToAddress(validatorKeyPair.getPublicKey()), signature);
}
static Hash hashForSignature(final AbstractIbftUnsignedMessageData unsignedMessageData) {
return Hash.hash(
BytesValues.concatenate(
BytesValues.ofUnsignedByte(unsignedMessageData.getMessageType()),
unsignedMessageData.encoded()));
}
private static Signature sign(
final AbstractIbftUnsignedMessageData unsignedMessageData, final KeyPair nodeKeys) {
return SECP256K1.sign(hashForSignature(unsignedMessageData), nodeKeys);
}
}

@ -1,62 +0,0 @@
/*
* 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.ibftmessagedata;
import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
import java.util.Collection;
public class IbftPreparedCertificate {
private final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> ibftPrePrepareMessage;
private final Collection<IbftSignedMessageData<IbftUnsignedPrepareMessageData>>
ibftPrepareMessages;
public IbftPreparedCertificate(
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> ibftPrePrepareMessage,
final Collection<IbftSignedMessageData<IbftUnsignedPrepareMessageData>> ibftPrepareMessages) {
this.ibftPrePrepareMessage = ibftPrePrepareMessage;
this.ibftPrepareMessages = ibftPrepareMessages;
}
public static IbftPreparedCertificate readFrom(final RLPInput rlpInput) {
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> ibftPrePreparedMessage;
final Collection<IbftSignedMessageData<IbftUnsignedPrepareMessageData>> ibftPrepareMessages;
rlpInput.enterList();
ibftPrePreparedMessage =
IbftSignedMessageData.readIbftSignedPrePrepareMessageDataFrom(rlpInput);
ibftPrepareMessages =
rlpInput.readList(IbftSignedMessageData::readIbftSignedPrepareMessageDataFrom);
rlpInput.leaveList();
return new IbftPreparedCertificate(ibftPrePreparedMessage, ibftPrepareMessages);
}
public void writeTo(final RLPOutput rlpOutput) {
rlpOutput.startList();
ibftPrePrepareMessage.writeTo(rlpOutput);
rlpOutput.writeList(ibftPrepareMessages, IbftSignedMessageData::writeTo);
rlpOutput.endList();
}
public IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> getIbftPrePrepareMessage() {
return ibftPrePrepareMessage;
}
public Collection<IbftSignedMessageData<IbftUnsignedPrepareMessageData>>
getIbftPrepareMessages() {
return ibftPrepareMessages;
}
}

@ -1,53 +0,0 @@
/*
* 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.ibftmessagedata;
import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
import java.util.Collection;
public class IbftRoundChangeCertificate {
private final Collection<IbftSignedMessageData<IbftUnsignedRoundChangeMessageData>>
ibftRoundChangeMessages;
public IbftRoundChangeCertificate(
final Collection<IbftSignedMessageData<IbftUnsignedRoundChangeMessageData>>
ibftRoundChangeMessages) {
this.ibftRoundChangeMessages = ibftRoundChangeMessages;
}
public static IbftRoundChangeCertificate readFrom(final RLPInput rlpInput) {
final Collection<IbftSignedMessageData<IbftUnsignedRoundChangeMessageData>>
ibftRoundChangeMessages;
rlpInput.enterList();
ibftRoundChangeMessages =
rlpInput.readList(IbftSignedMessageData::readIbftSignedRoundChangeMessageDataFrom);
rlpInput.leaveList();
return new IbftRoundChangeCertificate(ibftRoundChangeMessages);
}
public void writeTo(final RLPOutput rlpOutput) {
rlpOutput.startList();
rlpOutput.writeList(ibftRoundChangeMessages, IbftSignedMessageData::writeTo);
rlpOutput.endList();
}
public Collection<IbftSignedMessageData<IbftUnsignedRoundChangeMessageData>>
getIbftRoundChangeMessages() {
return ibftRoundChangeMessages;
}
}

@ -14,11 +14,10 @@ package tech.pegasys.pantheon.consensus.ibft.ibftmessagedata;
import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier; import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
public abstract class AbstractIbftUnsignedInRoundMessageData public abstract class InRoundPayload extends AbstractPayload {
extends AbstractIbftUnsignedMessageData {
protected final ConsensusRoundIdentifier roundIdentifier; protected final ConsensusRoundIdentifier roundIdentifier;
protected AbstractIbftUnsignedInRoundMessageData(final ConsensusRoundIdentifier roundIdentifier) { protected InRoundPayload(final ConsensusRoundIdentifier roundIdentifier) {
this.roundIdentifier = roundIdentifier; this.roundIdentifier = roundIdentifier;
} }

@ -0,0 +1,98 @@
/*
* 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.ibftmessagedata;
import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
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 tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.core.Util;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import java.util.Optional;
public class MessageFactory {
private final KeyPair validatorKeyPair;
public MessageFactory(final KeyPair validatorKeyPair) {
this.validatorKeyPair = validatorKeyPair;
}
public SignedData<ProposalPayload> createSignedProposalPayload(
final ConsensusRoundIdentifier roundIdentifier, final Block block) {
final ProposalPayload payload = new ProposalPayload(roundIdentifier, block);
return createSignedMessage(payload);
}
public SignedData<PreparePayload> createSignedPreparePayload(
final ConsensusRoundIdentifier roundIdentifier, final Hash digest) {
final PreparePayload payload = new PreparePayload(roundIdentifier, digest);
return createSignedMessage(payload);
}
public SignedData<CommitPayload> createSignedCommitPayload(
final ConsensusRoundIdentifier roundIdentifier,
final Hash digest,
final Signature commitSeal) {
final CommitPayload payload = new CommitPayload(roundIdentifier, digest, commitSeal);
return createSignedMessage(payload);
}
public SignedData<RoundChangePayload> createSignedRoundChangePayload(
final ConsensusRoundIdentifier roundIdentifier,
final Optional<PreparedCertificate> preparedCertificate) {
final RoundChangePayload payload = new RoundChangePayload(roundIdentifier, preparedCertificate);
return createSignedMessage(payload);
}
public SignedData<NewRoundPayload> createSignedNewRoundPayload(
final ConsensusRoundIdentifier roundIdentifier,
final RoundChangeCertificate roundChangeCertificate,
final SignedData<ProposalPayload> proposalPayload) {
final NewRoundPayload payload =
new NewRoundPayload(roundIdentifier, roundChangeCertificate, proposalPayload);
return createSignedMessage(payload);
}
private <M extends AbstractPayload> SignedData<M> createSignedMessage(final M payload) {
final Signature signature = sign(payload, validatorKeyPair);
return new SignedData<>(
payload, Util.publicKeyToAddress(validatorKeyPair.getPublicKey()), signature);
}
static Hash hashForSignature(final AbstractPayload unsignedMessageData) {
return Hash.hash(
BytesValues.concatenate(
BytesValues.ofUnsignedByte(unsignedMessageData.getMessageType()),
unsignedMessageData.encoded()));
}
private static Signature sign(final AbstractPayload unsignedMessageData, final KeyPair nodeKeys) {
return SECP256K1.sign(hashForSignature(unsignedMessageData), nodeKeys);
}
}

@ -17,35 +17,35 @@ import tech.pegasys.pantheon.consensus.ibft.ibftmessage.IbftV2;
import tech.pegasys.pantheon.ethereum.rlp.RLPInput; import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLPOutput; import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
public class IbftUnsignedNewRoundMessageData extends AbstractIbftUnsignedMessageData { public class NewRoundPayload extends AbstractPayload {
private static final int TYPE = IbftV2.NEW_ROUND; private static final int TYPE = IbftV2.NEW_ROUND;
private final ConsensusRoundIdentifier roundChangeIdentifier; private final ConsensusRoundIdentifier roundChangeIdentifier;
private final IbftRoundChangeCertificate roundChangeCertificate; private final RoundChangeCertificate roundChangeCertificate;
private final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> ibftPrePrepareMessage; private final SignedData<ProposalPayload> proposalPayload;
public IbftUnsignedNewRoundMessageData( public NewRoundPayload(
final ConsensusRoundIdentifier roundIdentifier, final ConsensusRoundIdentifier roundIdentifier,
final IbftRoundChangeCertificate roundChangeCertificate, final RoundChangeCertificate roundChangeCertificate,
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> ibftPrePrepareMessage) { final SignedData<ProposalPayload> proposalPayload) {
this.roundChangeIdentifier = roundIdentifier; this.roundChangeIdentifier = roundIdentifier;
this.roundChangeCertificate = roundChangeCertificate; this.roundChangeCertificate = roundChangeCertificate;
this.ibftPrePrepareMessage = ibftPrePrepareMessage; this.proposalPayload = proposalPayload;
} }
public ConsensusRoundIdentifier getRoundChangeIdentifier() { public ConsensusRoundIdentifier getRoundChangeIdentifier() {
return roundChangeIdentifier; return roundChangeIdentifier;
} }
public IbftRoundChangeCertificate getRoundChangeCertificate() { public RoundChangeCertificate getRoundChangeCertificate() {
return roundChangeCertificate; return roundChangeCertificate;
} }
public IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> getIbftPrePrepareMessage() { public SignedData<ProposalPayload> getProposalPayload() {
return ibftPrePrepareMessage; return proposalPayload;
} }
@Override @Override
@ -54,22 +54,20 @@ public class IbftUnsignedNewRoundMessageData extends AbstractIbftUnsignedMessage
rlpOutput.startList(); rlpOutput.startList();
roundChangeIdentifier.writeTo(rlpOutput); roundChangeIdentifier.writeTo(rlpOutput);
roundChangeCertificate.writeTo(rlpOutput); roundChangeCertificate.writeTo(rlpOutput);
ibftPrePrepareMessage.writeTo(rlpOutput); proposalPayload.writeTo(rlpOutput);
rlpOutput.endList(); rlpOutput.endList();
} }
public static IbftUnsignedNewRoundMessageData readFrom(final RLPInput rlpInput) { public static NewRoundPayload readFrom(final RLPInput rlpInput) {
rlpInput.enterList(); rlpInput.enterList();
final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundIdentifier.readFrom(rlpInput); final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundIdentifier.readFrom(rlpInput);
final IbftRoundChangeCertificate roundChangeCertificate = final RoundChangeCertificate roundChangeCertificate = RoundChangeCertificate.readFrom(rlpInput);
IbftRoundChangeCertificate.readFrom(rlpInput); final SignedData<ProposalPayload> proposalPayload =
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> ibftPrePrepareMessage = SignedData.readSignedProposalPayloadFrom(rlpInput);
IbftSignedMessageData.readIbftSignedPrePrepareMessageDataFrom(rlpInput);
rlpInput.leaveList(); rlpInput.leaveList();
return new IbftUnsignedNewRoundMessageData( return new NewRoundPayload(roundIdentifier, roundChangeCertificate, proposalPayload);
roundIdentifier, roundChangeCertificate, ibftPrePrepareMessage);
} }
@Override @Override

@ -18,24 +18,23 @@ import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.rlp.RLPInput; import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLPOutput; import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
public class IbftUnsignedPrepareMessageData extends AbstractIbftUnsignedInRoundMessageData { public class PreparePayload extends InRoundPayload {
private static final int TYPE = IbftV2.PREPARE; private static final int TYPE = IbftV2.PREPARE;
private final Hash digest; private final Hash digest;
public IbftUnsignedPrepareMessageData( public PreparePayload(final ConsensusRoundIdentifier roundIdentifier, final Hash digest) {
final ConsensusRoundIdentifier roundIdentifier, final Hash digest) {
super(roundIdentifier); super(roundIdentifier);
this.digest = digest; this.digest = digest;
} }
public static IbftUnsignedPrepareMessageData readFrom(final RLPInput rlpInput) { public static PreparePayload readFrom(final RLPInput rlpInput) {
rlpInput.enterList(); rlpInput.enterList();
final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundIdentifier.readFrom(rlpInput); final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundIdentifier.readFrom(rlpInput);
final Hash digest = readDigest(rlpInput); final Hash digest = readDigest(rlpInput);
rlpInput.leaveList(); rlpInput.leaveList();
return new IbftUnsignedPrepareMessageData(roundIdentifier, digest); return new PreparePayload(roundIdentifier, digest);
} }
@Override @Override

@ -0,0 +1,58 @@
/*
* 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.ibftmessagedata;
import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
import java.util.Collection;
public class PreparedCertificate {
private final SignedData<ProposalPayload> proposalPayload;
private final Collection<SignedData<PreparePayload>> preparePayloads;
public PreparedCertificate(
final SignedData<ProposalPayload> proposalPayload,
final Collection<SignedData<PreparePayload>> preparePayloads) {
this.proposalPayload = proposalPayload;
this.preparePayloads = preparePayloads;
}
public static PreparedCertificate readFrom(final RLPInput rlpInput) {
final SignedData<ProposalPayload> proposalMessage;
final Collection<SignedData<PreparePayload>> prepareMessages;
rlpInput.enterList();
proposalMessage = SignedData.readSignedProposalPayloadFrom(rlpInput);
prepareMessages = rlpInput.readList(SignedData::readSignedPreparePayloadFrom);
rlpInput.leaveList();
return new PreparedCertificate(proposalMessage, prepareMessages);
}
public void writeTo(final RLPOutput rlpOutput) {
rlpOutput.startList();
proposalPayload.writeTo(rlpOutput);
rlpOutput.writeList(preparePayloads, SignedData::writeTo);
rlpOutput.endList();
}
public SignedData<ProposalPayload> getProposalPayload() {
return proposalPayload;
}
public Collection<SignedData<PreparePayload>> getPreparePayloads() {
return preparePayloads;
}
}

@ -19,20 +19,17 @@ import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.rlp.RLPInput; import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLPOutput; import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
// NOTE: Implementation of all methods of this class is still pending. This class was added to show public class ProposalPayload extends InRoundPayload {
// how a PreparedCertificate is encoded and decoded inside a RoundChange message
public class IbftUnsignedPrePrepareMessageData extends AbstractIbftUnsignedInRoundMessageData {
private static final int TYPE = IbftV2.PRE_PREPARE; private static final int TYPE = IbftV2.PROPOSAL;
private final Block block; private final Block block;
public IbftUnsignedPrePrepareMessageData( public ProposalPayload(final ConsensusRoundIdentifier roundIdentifier, final Block block) {
final ConsensusRoundIdentifier roundIdentifier, final Block block) {
super(roundIdentifier); super(roundIdentifier);
this.block = block; this.block = block;
} }
public static IbftUnsignedPrePrepareMessageData readFrom(final RLPInput rlpInput) { public static ProposalPayload readFrom(final RLPInput rlpInput) {
rlpInput.enterList(); rlpInput.enterList();
final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundIdentifier.readFrom(rlpInput); final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundIdentifier.readFrom(rlpInput);
@ -40,7 +37,7 @@ public class IbftUnsignedPrePrepareMessageData extends AbstractIbftUnsignedInRou
Block.readFrom(rlpInput, IbftBlockHashing::calculateDataHashForCommittedSeal); Block.readFrom(rlpInput, IbftBlockHashing::calculateDataHashForCommittedSeal);
rlpInput.leaveList(); rlpInput.leaveList();
return new IbftUnsignedPrePrepareMessageData(roundIdentifier, block); return new ProposalPayload(roundIdentifier, block);
} }
@Override @Override

@ -0,0 +1,48 @@
/*
* 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.ibftmessagedata;
import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
import java.util.Collection;
public class RoundChangeCertificate {
private final Collection<SignedData<RoundChangePayload>> roundChangePayloads;
public RoundChangeCertificate(
final Collection<SignedData<RoundChangePayload>> roundChangePayloads) {
this.roundChangePayloads = roundChangePayloads;
}
public static RoundChangeCertificate readFrom(final RLPInput rlpInput) {
final Collection<SignedData<RoundChangePayload>> roundChangePayloads;
rlpInput.enterList();
roundChangePayloads = rlpInput.readList(SignedData::readSignedRoundChangePayloadFrom);
rlpInput.leaveList();
return new RoundChangeCertificate(roundChangePayloads);
}
public void writeTo(final RLPOutput rlpOutput) {
rlpOutput.startList();
rlpOutput.writeList(roundChangePayloads, SignedData::writeTo);
rlpOutput.endList();
}
public Collection<SignedData<RoundChangePayload>> getRoundChangePayloads() {
return roundChangePayloads;
}
}

@ -20,18 +20,18 @@ import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
import java.util.Optional; import java.util.Optional;
public class IbftUnsignedRoundChangeMessageData extends AbstractIbftUnsignedMessageData { public class RoundChangePayload extends AbstractPayload {
private static final int TYPE = IbftV2.PREPARE; private static final int TYPE = IbftV2.PREPARE;
private final ConsensusRoundIdentifier roundChangeIdentifier; private final ConsensusRoundIdentifier roundChangeIdentifier;
// The validator may not hae any prepared certificate // The validator may not hae any prepared certificate
private final Optional<IbftPreparedCertificate> preparedCertificate; private final Optional<PreparedCertificate> preparedCertificate;
public IbftUnsignedRoundChangeMessageData( public RoundChangePayload(
final ConsensusRoundIdentifier roundIdentifier, final ConsensusRoundIdentifier roundIdentifier,
final Optional<IbftPreparedCertificate> preparedCertificate) { final Optional<PreparedCertificate> preparedCertificate) {
this.roundChangeIdentifier = roundIdentifier; this.roundChangeIdentifier = roundIdentifier;
this.preparedCertificate = preparedCertificate; this.preparedCertificate = preparedCertificate;
} }
@ -40,7 +40,7 @@ public class IbftUnsignedRoundChangeMessageData extends AbstractIbftUnsignedMess
return roundChangeIdentifier; return roundChangeIdentifier;
} }
public Optional<IbftPreparedCertificate> getPreparedCertificate() { public Optional<PreparedCertificate> getPreparedCertificate() {
return preparedCertificate; return preparedCertificate;
} }
@ -59,21 +59,21 @@ public class IbftUnsignedRoundChangeMessageData extends AbstractIbftUnsignedMess
ibftMessage.endList(); ibftMessage.endList();
} }
public static IbftUnsignedRoundChangeMessageData readFrom(final RLPInput rlpInput) { public static RoundChangePayload readFrom(final RLPInput rlpInput) {
rlpInput.enterList(); rlpInput.enterList();
final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundIdentifier.readFrom(rlpInput); final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundIdentifier.readFrom(rlpInput);
final Optional<IbftPreparedCertificate> preparedCertificate; final Optional<PreparedCertificate> preparedCertificate;
if (rlpInput.nextIsNull()) { if (rlpInput.nextIsNull()) {
rlpInput.skipNext(); rlpInput.skipNext();
preparedCertificate = Optional.empty(); preparedCertificate = Optional.empty();
} else { } else {
preparedCertificate = Optional.of(IbftPreparedCertificate.readFrom(rlpInput)); preparedCertificate = Optional.of(PreparedCertificate.readFrom(rlpInput));
} }
rlpInput.leaveList(); rlpInput.leaveList();
return new IbftUnsignedRoundChangeMessageData(roundIdentifier, preparedCertificate); return new RoundChangePayload(roundIdentifier, preparedCertificate);
} }
@Override @Override

@ -20,15 +20,14 @@ import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLPOutput; import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
public class IbftSignedMessageData<M extends AbstractIbftUnsignedMessageData> { public class SignedData<M extends AbstractPayload> {
protected final Address sender; protected final Address sender;
protected final Signature signature; protected final Signature signature;
protected final M ibftUnsignedMessageData; protected final M unsignedPayload;
public IbftSignedMessageData( public SignedData(final M unsignedPayload, final Address sender, final Signature signature) {
final M ibftUnsignedMessageData, final Address sender, final Signature signature) { this.unsignedPayload = unsignedPayload;
this.ibftUnsignedMessageData = ibftUnsignedMessageData;
this.sender = sender; this.sender = sender;
this.signature = signature; this.signature = signature;
} }
@ -41,14 +40,14 @@ public class IbftSignedMessageData<M extends AbstractIbftUnsignedMessageData> {
return signature; return signature;
} }
public M getUnsignedMessageData() { public M getPayload() {
return ibftUnsignedMessageData; return unsignedPayload;
} }
public void writeTo(final RLPOutput output) { public void writeTo(final RLPOutput output) {
output.startList(); output.startList();
ibftUnsignedMessageData.writeTo(output); unsignedPayload.writeTo(output);
output.writeBytesValue(getSignature().encodedBytes()); output.writeBytesValue(getSignature().encodedBytes());
output.endList(); output.endList();
} }
@ -59,72 +58,63 @@ public class IbftSignedMessageData<M extends AbstractIbftUnsignedMessageData> {
return rlpEncode.encoded(); return rlpEncode.encoded();
} }
public static IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> public static SignedData<ProposalPayload> readSignedProposalPayloadFrom(final RLPInput rlpInput) {
readIbftSignedPrePrepareMessageDataFrom(final RLPInput rlpInput) {
rlpInput.enterList(); rlpInput.enterList();
final IbftUnsignedPrePrepareMessageData unsignedMessageData = final ProposalPayload unsignedMessageData = ProposalPayload.readFrom(rlpInput);
IbftUnsignedPrePrepareMessageData.readFrom(rlpInput);
final Signature signature = readSignature(rlpInput); final Signature signature = readSignature(rlpInput);
rlpInput.leaveList(); rlpInput.leaveList();
return from(unsignedMessageData, signature); return from(unsignedMessageData, signature);
} }
public static IbftSignedMessageData<IbftUnsignedPrepareMessageData> public static SignedData<PreparePayload> readSignedPreparePayloadFrom(final RLPInput rlpInput) {
readIbftSignedPrepareMessageDataFrom(final RLPInput rlpInput) {
rlpInput.enterList(); rlpInput.enterList();
final IbftUnsignedPrepareMessageData unsignedMessageData = final PreparePayload unsignedMessageData = PreparePayload.readFrom(rlpInput);
IbftUnsignedPrepareMessageData.readFrom(rlpInput);
final Signature signature = readSignature(rlpInput); final Signature signature = readSignature(rlpInput);
rlpInput.leaveList(); rlpInput.leaveList();
return from(unsignedMessageData, signature); return from(unsignedMessageData, signature);
} }
public static IbftSignedMessageData<IbftUnsignedCommitMessageData> public static SignedData<CommitPayload> readSignedCommitPayloadFrom(final RLPInput rlpInput) {
readIbftSignedCommitMessageDataFrom(final RLPInput rlpInput) {
rlpInput.enterList(); rlpInput.enterList();
final IbftUnsignedCommitMessageData unsignedMessageData = final CommitPayload unsignedMessageData = CommitPayload.readFrom(rlpInput);
IbftUnsignedCommitMessageData.readFrom(rlpInput);
final Signature signature = readSignature(rlpInput); final Signature signature = readSignature(rlpInput);
rlpInput.leaveList(); rlpInput.leaveList();
return from(unsignedMessageData, signature); return from(unsignedMessageData, signature);
} }
public static IbftSignedMessageData<IbftUnsignedRoundChangeMessageData> public static SignedData<RoundChangePayload> readSignedRoundChangePayloadFrom(
readIbftSignedRoundChangeMessageDataFrom(final RLPInput rlpInput) { final RLPInput rlpInput) {
rlpInput.enterList(); rlpInput.enterList();
final IbftUnsignedRoundChangeMessageData unsignedMessageData = final RoundChangePayload unsignedMessageData = RoundChangePayload.readFrom(rlpInput);
IbftUnsignedRoundChangeMessageData.readFrom(rlpInput);
final Signature signature = readSignature(rlpInput); final Signature signature = readSignature(rlpInput);
rlpInput.leaveList(); rlpInput.leaveList();
return from(unsignedMessageData, signature); return from(unsignedMessageData, signature);
} }
public static IbftSignedMessageData<IbftUnsignedNewRoundMessageData> public static SignedData<NewRoundPayload> readSignedNewRoundPayloadFrom(final RLPInput rlpInput) {
readIbftSignedNewRoundMessageDataFrom(final RLPInput rlpInput) {
rlpInput.enterList(); rlpInput.enterList();
final IbftUnsignedNewRoundMessageData unsignedMessageData = final NewRoundPayload unsignedMessageData = NewRoundPayload.readFrom(rlpInput);
IbftUnsignedNewRoundMessageData.readFrom(rlpInput);
final Signature signature = readSignature(rlpInput); final Signature signature = readSignature(rlpInput);
rlpInput.leaveList(); rlpInput.leaveList();
return from(unsignedMessageData, signature); return from(unsignedMessageData, signature);
} }
protected static <M extends AbstractIbftUnsignedMessageData> IbftSignedMessageData<M> from( protected static <M extends AbstractPayload> SignedData<M> from(
final M unsignedMessageData, final Signature signature) { final M unsignedMessageData, final Signature signature) {
final Address sender = recoverSender(unsignedMessageData, signature); final Address sender = recoverSender(unsignedMessageData, signature);
return new IbftSignedMessageData<>(unsignedMessageData, sender, signature); return new SignedData<>(unsignedMessageData, sender, signature);
} }
protected static Signature readSignature(final RLPInput signedMessage) { protected static Signature readSignature(final RLPInput signedMessage) {
@ -132,9 +122,8 @@ public class IbftSignedMessageData<M extends AbstractIbftUnsignedMessageData> {
} }
protected static Address recoverSender( protected static Address recoverSender(
final AbstractIbftUnsignedMessageData unsignedMessageData, final Signature signature) { final AbstractPayload unsignedMessageData, final Signature signature) {
return Util.signatureToAddress( return Util.signatureToAddress(signature, MessageFactory.hashForSignature(unsignedMessageData));
signature, IbftMessageFactory.hashForSignature(unsignedMessageData));
} }
} }

@ -40,7 +40,7 @@ public class IbftSubProtocol implements SubProtocol {
@Override @Override
public boolean isValidMessageCode(final int protocolVersion, final int code) { public boolean isValidMessageCode(final int protocolVersion, final int code) {
switch (code) { switch (code) {
case IbftV2.PRE_PREPARE: case IbftV2.PROPOSAL:
case IbftV2.PREPARE: case IbftV2.PREPARE:
case IbftV2.COMMIT: case IbftV2.COMMIT:
case IbftV2.ROUND_CHANGE: case IbftV2.ROUND_CHANGE:

@ -17,11 +17,11 @@ 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;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.AbstractIbftUnsignedInRoundMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.CommitPayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftSignedMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.InRoundPayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftUnsignedCommitMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.PreparePayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftUnsignedPrePrepareMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.ProposalPayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftUnsignedPrepareMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.SignedData;
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;
@ -47,8 +47,7 @@ public class MessageValidator {
private final ProtocolContext<IbftContext> protocolContext; private final ProtocolContext<IbftContext> protocolContext;
private final BlockHeader parentHeader; private final BlockHeader parentHeader;
private Optional<IbftSignedMessageData<IbftUnsignedPrePrepareMessageData>> preprepareMessage = private Optional<SignedData<ProposalPayload>> proposal = Optional.empty();
Optional.empty();
public MessageValidator( public MessageValidator(
final Collection<Address> validators, final Collection<Address> validators,
@ -65,41 +64,39 @@ public class MessageValidator {
this.parentHeader = parentHeader; this.parentHeader = parentHeader;
} }
public boolean addPreprepareMessage( public boolean addSignedProposalPayload(final SignedData<ProposalPayload> msg) {
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> msg) {
if (preprepareMessage.isPresent()) { if (proposal.isPresent()) {
return handleSubsequentPreprepareMessage(preprepareMessage.get(), msg); return handleSubsequentProposal(proposal.get(), msg);
} }
if (!validatePreprepareMessage(msg)) { if (!validateSignedProposalPayload(msg)) {
return false; return false;
} }
if (!validateBlocKMatchesPrepareMessageRound(msg.getUnsignedMessageData())) { if (!validateBlockMatchesProposalRound(msg.getPayload())) {
return false; return false;
} }
preprepareMessage = Optional.of(msg); proposal = Optional.of(msg);
return true; return true;
} }
private boolean validatePreprepareMessage( private boolean validateSignedProposalPayload(final SignedData<ProposalPayload> msg) {
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> msg) {
if (!msg.getUnsignedMessageData().getRoundIdentifier().equals(roundIdentifier)) { if (!msg.getPayload().getRoundIdentifier().equals(roundIdentifier)) {
LOG.info("Invalid Preprepare message, does not match current round."); LOG.info("Invalid Proposal message, does not match current round.");
return false; return false;
} }
if (!msg.getSender().equals(expectedProposer)) { if (!msg.getSender().equals(expectedProposer)) {
LOG.info( LOG.info(
"Invalid Preprepare message, was not created by the proposer expected for the " "Invalid Proposal message, was not created by the proposer expected for the "
+ "associated round."); + "associated round.");
return false; return false;
} }
final Block proposedBlock = msg.getUnsignedMessageData().getBlock(); final Block proposedBlock = msg.getPayload().getBlock();
if (!headerValidator.validateHeader( if (!headerValidator.validateHeader(
proposedBlock.getHeader(), parentHeader, protocolContext, FULL)) { proposedBlock.getHeader(), parentHeader, protocolContext, FULL)) {
LOG.info("Invalid Prepare message, block did not pass header validation."); LOG.info("Invalid Prepare message, block did not pass header validation.");
@ -109,30 +106,28 @@ public class MessageValidator {
return true; return true;
} }
private boolean handleSubsequentPreprepareMessage( private boolean handleSubsequentProposal(
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> existingMsg, final SignedData<ProposalPayload> existingMsg, final SignedData<ProposalPayload> newMsg) {
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> newMsg) {
if (!existingMsg.getSender().equals(newMsg.getSender())) { if (!existingMsg.getSender().equals(newMsg.getSender())) {
LOG.debug("Received subsequent invalid Preprepare message; sender differs from original."); LOG.debug("Received subsequent invalid Proposal message; sender differs from original.");
return false; return false;
} }
final IbftUnsignedPrePrepareMessageData existingData = existingMsg.getUnsignedMessageData(); final ProposalPayload existingData = existingMsg.getPayload();
final IbftUnsignedPrePrepareMessageData newData = newMsg.getUnsignedMessageData(); final ProposalPayload newData = newMsg.getPayload();
if (!preprepareMessagesAreIdentical(existingData, newData)) { if (!proposalMessagesAreIdentical(existingData, newData)) {
LOG.debug("Received subsequent invalid Preprepare message; content differs from original."); LOG.debug("Received subsequent invalid Proposal message; content differs from original.");
return false; return false;
} }
return true; return true;
} }
public boolean validatePrepareMessage( public boolean validatePrepareMessage(final SignedData<PreparePayload> msg) {
final IbftSignedMessageData<IbftUnsignedPrepareMessageData> msg) {
final String msgType = "Prepare"; final String msgType = "Prepare";
if (!isMessageForCurrentRoundFromValidatorAndPreprareMessageAvailable(msg, msgType)) { if (!isMessageForCurrentRoundFromValidatorAndProposalAvailable(msg, msgType)) {
return false; return false;
} }
@ -141,35 +136,32 @@ public class MessageValidator {
return false; return false;
} }
return validateDigestMatchesPreprepareBlock(msg.getUnsignedMessageData().getDigest(), msgType); return validateDigestMatchesProposal(msg.getPayload().getDigest(), msgType);
} }
public boolean validateCommmitMessage( public boolean validateCommmitMessage(final SignedData<CommitPayload> msg) {
final IbftSignedMessageData<IbftUnsignedCommitMessageData> msg) {
final String msgType = "Commit"; final String msgType = "Commit";
if (!isMessageForCurrentRoundFromValidatorAndPreprareMessageAvailable(msg, msgType)) { if (!isMessageForCurrentRoundFromValidatorAndProposalAvailable(msg, msgType)) {
return false; return false;
} }
final Block proposedBlock = preprepareMessage.get().getUnsignedMessageData().getBlock(); final Block proposedBlock = proposal.get().getPayload().getBlock();
final Address commitSealCreator = final Address commitSealCreator =
Util.signatureToAddress( Util.signatureToAddress(msg.getPayload().getCommitSeal(), proposedBlock.getHash());
msg.getUnsignedMessageData().getCommitSeal(), proposedBlock.getHash());
if (!commitSealCreator.equals(msg.getSender())) { if (!commitSealCreator.equals(msg.getSender())) {
LOG.info("Invalid Commit message. Seal was not created by the message transmitter."); LOG.info("Invalid Commit message. Seal was not created by the message transmitter.");
return false; return false;
} }
return validateDigestMatchesPreprepareBlock(msg.getUnsignedMessageData().getDigest(), msgType); return validateDigestMatchesProposal(msg.getPayload().getDigest(), msgType);
} }
private boolean isMessageForCurrentRoundFromValidatorAndPreprareMessageAvailable( private boolean isMessageForCurrentRoundFromValidatorAndProposalAvailable(
final IbftSignedMessageData<? extends AbstractIbftUnsignedInRoundMessageData> msg, final SignedData<? extends InRoundPayload> msg, final String msgType) {
final String msgType) {
if (!msg.getUnsignedMessageData().getRoundIdentifier().equals(roundIdentifier)) { if (!msg.getPayload().getRoundIdentifier().equals(roundIdentifier)) {
LOG.info("Invalid {} message, does not match current round.", msgType); LOG.info("Invalid {} message, does not match current round.", msgType);
return false; return false;
} }
@ -181,18 +173,18 @@ public class MessageValidator {
return false; return false;
} }
if (!preprepareMessage.isPresent()) { if (!proposal.isPresent()) {
LOG.info( LOG.info(
"Unable to validate {} message. No Preprepare message exists against " "Unable to validate {} message. No Proposal exists against which to validate "
+ "which to validate block digest.", + "block digest.",
msgType); msgType);
return false; return false;
} }
return true; return true;
} }
private boolean validateDigestMatchesPreprepareBlock(final Hash digest, final String msgType) { private boolean validateDigestMatchesProposal(final Hash digest, final String msgType) {
final Block proposedBlock = preprepareMessage.get().getUnsignedMessageData().getBlock(); final Block proposedBlock = proposal.get().getPayload().getBlock();
if (!digest.equals(proposedBlock.getHash())) { if (!digest.equals(proposedBlock.getHash())) {
LOG.info( LOG.info(
"Illegal {} message, digest does not match the block in the Prepare Message.", msgType); "Illegal {} message, digest does not match the block in the Prepare Message.", msgType);
@ -201,19 +193,18 @@ public class MessageValidator {
return true; return true;
} }
private boolean preprepareMessagesAreIdentical( private boolean proposalMessagesAreIdentical(
final IbftUnsignedPrePrepareMessageData right, final IbftUnsignedPrePrepareMessageData left) { final ProposalPayload right, final ProposalPayload left) {
return right.getBlock().getHash().equals(left.getBlock().getHash()) return right.getBlock().getHash().equals(left.getBlock().getHash())
&& right.getRoundIdentifier().equals(left.getRoundIdentifier()); && right.getRoundIdentifier().equals(left.getRoundIdentifier());
} }
private boolean validateBlocKMatchesPrepareMessageRound( private boolean validateBlockMatchesProposalRound(final ProposalPayload payload) {
final IbftUnsignedPrePrepareMessageData msgData) { final ConsensusRoundIdentifier msgRound = payload.getRoundIdentifier();
final ConsensusRoundIdentifier msgRound = msgData.getRoundIdentifier();
final IbftExtraData extraData = final IbftExtraData extraData =
IbftExtraData.decode(msgData.getBlock().getHeader().getExtraData()); IbftExtraData.decode(payload.getBlock().getHeader().getExtraData());
if (extraData.getRound() != msgRound.getRoundNumber()) { if (extraData.getRound() != msgRound.getRoundNumber()) {
LOG.info("Invalid Preprepare message, round number in block does not match that in message."); LOG.info("Invalid Proposal message, round number in block does not match that in message.");
return false; return false;
} }
return true; return true;

@ -13,11 +13,11 @@
package tech.pegasys.pantheon.consensus.ibft.validation; package tech.pegasys.pantheon.consensus.ibft.validation;
import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier; import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftPreparedCertificate; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.PreparePayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftSignedMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.PreparedCertificate;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftUnsignedPrePrepareMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.ProposalPayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftUnsignedPrepareMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.RoundChangePayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftUnsignedRoundChangeMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.SignedData;
import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.Address;
import java.util.Collection; import java.util.Collection;
@ -45,8 +45,7 @@ public class RoundChangeMessageValidator {
this.currentRound = currentRound; this.currentRound = currentRound;
} }
public boolean validateMessage( public boolean validateMessage(final SignedData<RoundChangePayload> msg) {
final IbftSignedMessageData<IbftUnsignedRoundChangeMessageData> msg) {
if (!validators.contains(msg.getSender())) { if (!validators.contains(msg.getSender())) {
LOG.info( LOG.info(
@ -55,33 +54,30 @@ public class RoundChangeMessageValidator {
return false; return false;
} }
final ConsensusRoundIdentifier roundChangeTarget = final ConsensusRoundIdentifier targetRound = msg.getPayload().getRoundChangeIdentifier();
msg.getUnsignedMessageData().getRoundChangeIdentifier();
if (roundChangeTarget.getSequenceNumber() != currentRound.getSequenceNumber()) { if (targetRound.getSequenceNumber() != currentRound.getSequenceNumber()) {
LOG.info("Invalid RoundChange message, not valid for local chain height."); LOG.info("Invalid RoundChange message, not valid for local chain height.");
return false; return false;
} }
if (msg.getUnsignedMessageData().getPreparedCertificate().isPresent()) { if (msg.getPayload().getPreparedCertificate().isPresent()) {
final IbftPreparedCertificate certificate = final PreparedCertificate certificate = msg.getPayload().getPreparedCertificate().get();
msg.getUnsignedMessageData().getPreparedCertificate().get();
return validatePrepareCertificate(certificate, roundChangeTarget); return validatePrepareCertificate(certificate, targetRound);
} }
return true; return true;
} }
private boolean validatePrepareCertificate( private boolean validatePrepareCertificate(
final IbftPreparedCertificate certificate, final ConsensusRoundIdentifier roundChangeTarget) { final PreparedCertificate certificate, final ConsensusRoundIdentifier roundChangeTarget) {
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> preprepareMessage = final SignedData<ProposalPayload> proposalMessage = certificate.getProposalPayload();
certificate.getIbftPrePrepareMessage();
final ConsensusRoundIdentifier prepareCertRound = final ConsensusRoundIdentifier prepareCertRound =
preprepareMessage.getUnsignedMessageData().getRoundIdentifier(); proposalMessage.getPayload().getRoundIdentifier();
if (!validatePreprepareCertificateRound(prepareCertRound, roundChangeTarget)) { if (!validatePreparedCertificateRound(prepareCertRound, roundChangeTarget)) {
return false; return false;
} }
@ -90,22 +86,21 @@ public class RoundChangeMessageValidator {
} }
private boolean validateConsistencyOfPrepareCertificateMessages( private boolean validateConsistencyOfPrepareCertificateMessages(
final IbftPreparedCertificate certificate, final MessageValidator messageValidator) { final PreparedCertificate certificate, final MessageValidator messageValidator) {
if (!messageValidator.addPreprepareMessage(certificate.getIbftPrePrepareMessage())) { if (!messageValidator.addSignedProposalPayload(certificate.getProposalPayload())) {
LOG.info("Invalid RoundChange message, embedded Preprepare message failed validation."); LOG.info("Invalid RoundChange message, embedded Proposal message failed validation.");
return false; return false;
} }
if (certificate.getIbftPrepareMessages().size() < minimumPrepareMessages) { if (certificate.getPreparePayloads().size() < minimumPrepareMessages) {
LOG.info( LOG.info(
"Invalid RoundChange message, insufficient prepare messages exist to justify " "Invalid RoundChange message, insufficient Prepare messages exist to justify "
+ "prepare certificate."); + "prepare certificate.");
return false; return false;
} }
for (final IbftSignedMessageData<IbftUnsignedPrepareMessageData> prepareMsg : for (final SignedData<PreparePayload> prepareMsg : certificate.getPreparePayloads()) {
certificate.getIbftPrepareMessages()) {
if (!messageValidator.validatePrepareMessage(prepareMsg)) { if (!messageValidator.validatePrepareMessage(prepareMsg)) {
LOG.info("Invalid RoundChange message, embedded Prepare message failed validation."); LOG.info("Invalid RoundChange message, embedded Prepare message failed validation.");
return false; return false;
@ -115,18 +110,18 @@ public class RoundChangeMessageValidator {
return true; return true;
} }
private boolean validatePreprepareCertificateRound( private boolean validatePreparedCertificateRound(
final ConsensusRoundIdentifier prepareCertRound, final ConsensusRoundIdentifier prepareCertRound,
final ConsensusRoundIdentifier roundChangeTarget) { final ConsensusRoundIdentifier roundChangeTarget) {
if (prepareCertRound.getSequenceNumber() != roundChangeTarget.getSequenceNumber()) { if (prepareCertRound.getSequenceNumber() != roundChangeTarget.getSequenceNumber()) {
LOG.info("Invalid RoundChange message, PreprepareCertificate is not for local chain height."); LOG.info("Invalid RoundChange message, PreparedCertificate is not for local chain height.");
return false; return false;
} }
if (prepareCertRound.getRoundNumber() >= roundChangeTarget.getRoundNumber()) { if (prepareCertRound.getRoundNumber() >= roundChangeTarget.getRoundNumber()) {
LOG.info( LOG.info(
"Invalid RoundChange message, PreprepareCertificate is newer than RoundChange target."); "Invalid RoundChange message, PreparedCertificate is newer than RoundChange target.");
return false; return false;
} }
return true; return true;

@ -20,11 +20,11 @@ import static org.mockito.Mockito.when;
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;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftMessageFactory; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.CommitPayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftSignedMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.MessageFactory;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftUnsignedCommitMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.PreparePayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftUnsignedPrePrepareMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.ProposalPayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftUnsignedPrepareMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.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.ProtocolContext; import tech.pegasys.pantheon.ethereum.ProtocolContext;
@ -55,10 +55,9 @@ public class MessageValidatorTest {
private final KeyPair proposerKey = KeyPair.generate(); private final KeyPair proposerKey = KeyPair.generate();
private final KeyPair validatorKey = KeyPair.generate(); private final KeyPair validatorKey = KeyPair.generate();
private final KeyPair nonValidatorKey = KeyPair.generate(); private final KeyPair nonValidatorKey = KeyPair.generate();
private final IbftMessageFactory proposerMessageFactory = new IbftMessageFactory(proposerKey); private final MessageFactory proposerMessageFactory = new MessageFactory(proposerKey);
private final IbftMessageFactory validatorMessageFactory = new IbftMessageFactory(validatorKey); private final MessageFactory validatorMessageFactory = new MessageFactory(validatorKey);
private final IbftMessageFactory nonValidatorMessageFactory = private final MessageFactory nonValidatorMessageFactory = new MessageFactory(nonValidatorKey);
new IbftMessageFactory(nonValidatorKey);
private final List<Address> validators = Lists.newArrayList(); private final List<Address> validators = Lists.newArrayList();
@ -107,16 +106,16 @@ public class MessageValidatorTest {
@Test @Test
public void receivingAPrepareMessageBeforePrePrepareFails() { public void receivingAPrepareMessageBeforePrePrepareFails() {
final IbftSignedMessageData<IbftUnsignedPrepareMessageData> prepareMsg = final SignedData<PreparePayload> prepareMsg =
proposerMessageFactory.createIbftSignedPrepareMessageData(roundIdentifier, Hash.ZERO); proposerMessageFactory.createSignedPreparePayload(roundIdentifier, Hash.ZERO);
assertThat(validator.validatePrepareMessage(prepareMsg)).isFalse(); assertThat(validator.validatePrepareMessage(prepareMsg)).isFalse();
} }
@Test @Test
public void receivingACommitMessageBeforePreprepareFails() { public void receivingACommitMessageBeforePreprepareFails() {
final IbftSignedMessageData<IbftUnsignedCommitMessageData> commitMsg = final SignedData<CommitPayload> commitMsg =
proposerMessageFactory.createIbftSignedCommitMessageData( proposerMessageFactory.createSignedCommitPayload(
roundIdentifier, Hash.ZERO, SECP256K1.sign(Hash.ZERO, proposerKey)); roundIdentifier, Hash.ZERO, SECP256K1.sign(Hash.ZERO, proposerKey));
assertThat(validator.validateCommmitMessage(commitMsg)).isFalse(); assertThat(validator.validateCommmitMessage(commitMsg)).isFalse();
@ -124,48 +123,46 @@ public class MessageValidatorTest {
@Test @Test
public void receivingPreprepareMessageFromNonProposerFails() { public void receivingPreprepareMessageFromNonProposerFails() {
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> preprepareMsg = final SignedData<ProposalPayload> preprepareMsg =
validatorMessageFactory.createIbftSignedPrePrepareMessageData( validatorMessageFactory.createSignedProposalPayload(roundIdentifier, mock(Block.class));
roundIdentifier, mock(Block.class));
assertThat(validator.addPreprepareMessage(preprepareMsg)).isFalse(); assertThat(validator.addSignedProposalPayload(preprepareMsg)).isFalse();
} }
@Test @Test
public void receivingPreprepareMessageWithIllegalBlockFails() { public void receivingPreprepareMessageWithIllegalBlockFails() {
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(false); when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(false);
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> preprepareMsg = final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createIbftSignedPrePrepareMessageData( proposerMessageFactory.createSignedProposalPayload(roundIdentifier, mock(Block.class));
roundIdentifier, mock(Block.class));
assertThat(validator.addPreprepareMessage(preprepareMsg)).isFalse(); assertThat(validator.addSignedProposalPayload(preprepareMsg)).isFalse();
} }
@Test @Test
public void receivingPrepareFromProposerFails() { public void receivingPrepareFromProposerFails() {
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true);
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> preprepareMsg = final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createIbftSignedPrePrepareMessageData(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
final IbftSignedMessageData<IbftUnsignedPrepareMessageData> prepareMsg = final SignedData<PreparePayload> prepareMsg =
proposerMessageFactory.createIbftSignedPrepareMessageData(roundIdentifier, block.getHash()); proposerMessageFactory.createSignedPreparePayload(roundIdentifier, block.getHash());
assertThat(validator.addPreprepareMessage(preprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(preprepareMsg)).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); when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true);
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> preprepareMsg =
proposerMessageFactory.createIbftSignedPrePrepareMessageData(roundIdentifier, block);
final IbftSignedMessageData<IbftUnsignedPrepareMessageData> prepareMsg = final SignedData<ProposalPayload> preprepareMsg =
nonValidatorMessageFactory.createIbftSignedPrepareMessageData( proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
roundIdentifier, block.getHash());
assertThat(validator.addPreprepareMessage(preprepareMsg)).isTrue(); final SignedData<PreparePayload> prepareMsg =
nonValidatorMessageFactory.createSignedPreparePayload(roundIdentifier, block.getHash());
assertThat(validator.addSignedProposalPayload(preprepareMsg)).isTrue();
assertThat(validator.validatePrepareMessage(prepareMsg)).isFalse(); assertThat(validator.validatePrepareMessage(prepareMsg)).isFalse();
} }
@ -173,20 +170,19 @@ public class MessageValidatorTest {
public void receivingMessagesWithDifferentRoundIdFromPreprepareFails() { public void receivingMessagesWithDifferentRoundIdFromPreprepareFails() {
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true);
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> preprepareMsg = final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createIbftSignedPrePrepareMessageData(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
final ConsensusRoundIdentifier invalidRoundIdentifier = final ConsensusRoundIdentifier invalidRoundIdentifier =
new ConsensusRoundIdentifier( new ConsensusRoundIdentifier(
roundIdentifier.getSequenceNumber(), roundIdentifier.getRoundNumber() + 1); roundIdentifier.getSequenceNumber(), roundIdentifier.getRoundNumber() + 1);
final IbftSignedMessageData<IbftUnsignedPrepareMessageData> prepareMsg = final SignedData<PreparePayload> prepareMsg =
validatorMessageFactory.createIbftSignedPrepareMessageData( validatorMessageFactory.createSignedPreparePayload(invalidRoundIdentifier, block.getHash());
invalidRoundIdentifier, block.getHash()); final SignedData<CommitPayload> commitMsg =
final IbftSignedMessageData<IbftUnsignedCommitMessageData> commitMsg = validatorMessageFactory.createSignedCommitPayload(
validatorMessageFactory.createIbftSignedCommitMessageData(
invalidRoundIdentifier, block.getHash(), SECP256K1.sign(block.getHash(), proposerKey)); invalidRoundIdentifier, block.getHash(), SECP256K1.sign(block.getHash(), proposerKey));
assertThat(validator.addPreprepareMessage(preprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(preprepareMsg)).isTrue();
assertThat(validator.validatePrepareMessage(prepareMsg)).isFalse(); assertThat(validator.validatePrepareMessage(prepareMsg)).isFalse();
assertThat(validator.validateCommmitMessage(commitMsg)).isFalse(); assertThat(validator.validateCommmitMessage(commitMsg)).isFalse();
} }
@ -195,13 +191,12 @@ public class MessageValidatorTest {
public void receivingPrepareNonProposerValidatorWithCorrectRoundIsSuccessful() { public void receivingPrepareNonProposerValidatorWithCorrectRoundIsSuccessful() {
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true);
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> preprepareMsg = final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createIbftSignedPrePrepareMessageData(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
final IbftSignedMessageData<IbftUnsignedPrepareMessageData> prepareMsg = final SignedData<PreparePayload> prepareMsg =
validatorMessageFactory.createIbftSignedPrepareMessageData( validatorMessageFactory.createSignedPreparePayload(roundIdentifier, block.getHash());
roundIdentifier, block.getHash());
assertThat(validator.addPreprepareMessage(preprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(preprepareMsg)).isTrue();
assertThat(validator.validatePrepareMessage(prepareMsg)).isTrue(); assertThat(validator.validatePrepareMessage(prepareMsg)).isTrue();
} }
@ -209,14 +204,14 @@ public class MessageValidatorTest {
public void receivingACommitMessageWithAnInvalidCommitSealFails() { public void receivingACommitMessageWithAnInvalidCommitSealFails() {
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true);
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> preprepareMsg = final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createIbftSignedPrePrepareMessageData(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
final IbftSignedMessageData<IbftUnsignedCommitMessageData> commitMsg = final SignedData<CommitPayload> commitMsg =
proposerMessageFactory.createIbftSignedCommitMessageData( proposerMessageFactory.createSignedCommitPayload(
roundIdentifier, block.getHash(), SECP256K1.sign(block.getHash(), nonValidatorKey)); roundIdentifier, block.getHash(), SECP256K1.sign(block.getHash(), nonValidatorKey));
assertThat(validator.addPreprepareMessage(preprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(preprepareMsg)).isTrue();
assertThat(validator.validateCommmitMessage(commitMsg)).isFalse(); assertThat(validator.validateCommmitMessage(commitMsg)).isFalse();
} }
@ -224,18 +219,18 @@ public class MessageValidatorTest {
public void commitMessageContainingValidSealFromValidatorIsSuccessful() { public void commitMessageContainingValidSealFromValidatorIsSuccessful() {
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true);
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> preprepareMsg = final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createIbftSignedPrePrepareMessageData(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
final IbftSignedMessageData<IbftUnsignedCommitMessageData> proposerCommitMsg = final SignedData<CommitPayload> proposerCommitMsg =
proposerMessageFactory.createIbftSignedCommitMessageData( proposerMessageFactory.createSignedCommitPayload(
roundIdentifier, block.getHash(), SECP256K1.sign(block.getHash(), proposerKey)); roundIdentifier, block.getHash(), SECP256K1.sign(block.getHash(), proposerKey));
final IbftSignedMessageData<IbftUnsignedCommitMessageData> validatorCommitMsg = final SignedData<CommitPayload> validatorCommitMsg =
validatorMessageFactory.createIbftSignedCommitMessageData( validatorMessageFactory.createSignedCommitPayload(
roundIdentifier, block.getHash(), SECP256K1.sign(block.getHash(), validatorKey)); roundIdentifier, block.getHash(), SECP256K1.sign(block.getHash(), validatorKey));
assertThat(validator.addPreprepareMessage(preprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(preprepareMsg)).isTrue();
assertThat(validator.validateCommmitMessage(proposerCommitMsg)).isTrue(); assertThat(validator.validateCommmitMessage(proposerCommitMsg)).isTrue();
assertThat(validator.validateCommmitMessage(validatorCommitMsg)).isTrue(); assertThat(validator.validateCommmitMessage(validatorCommitMsg)).isTrue();
} }
@ -244,39 +239,39 @@ public class MessageValidatorTest {
public void subsequentPreprepareHasDifferentSenderFails() { public void subsequentPreprepareHasDifferentSenderFails() {
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true);
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> preprepareMsg = final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createIbftSignedPrePrepareMessageData(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
assertThat(validator.addPreprepareMessage(preprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(preprepareMsg)).isTrue();
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> secondPreprepareMsg = final SignedData<ProposalPayload> secondPreprepareMsg =
validatorMessageFactory.createIbftSignedPrePrepareMessageData(roundIdentifier, block); validatorMessageFactory.createSignedProposalPayload(roundIdentifier, block);
assertThat(validator.addPreprepareMessage(secondPreprepareMsg)).isFalse(); assertThat(validator.addSignedProposalPayload(secondPreprepareMsg)).isFalse();
} }
@Test @Test
public void subsequentPreprepareHasDifferentContentFails() { public void subsequentPreprepareHasDifferentContentFails() {
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> preprepareMsg = final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createIbftSignedPrePrepareMessageData(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
assertThat(validator.addPreprepareMessage(preprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(preprepareMsg)).isTrue();
final ConsensusRoundIdentifier newRoundIdentifier = new ConsensusRoundIdentifier(3, 0); final ConsensusRoundIdentifier newRoundIdentifier = new ConsensusRoundIdentifier(3, 0);
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> secondPreprepareMsg = final SignedData<ProposalPayload> secondPreprepareMsg =
proposerMessageFactory.createIbftSignedPrePrepareMessageData(newRoundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(newRoundIdentifier, block);
assertThat(validator.addPreprepareMessage(secondPreprepareMsg)).isFalse(); assertThat(validator.addSignedProposalPayload(secondPreprepareMsg)).isFalse();
} }
@Test @Test
public void subsequentPreprepareHasIdenticalSenderAndContentIsSuccessful() { public void subsequentPreprepareHasIdenticalSenderAndContentIsSuccessful() {
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true);
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> preprepareMsg = final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createIbftSignedPrePrepareMessageData(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
assertThat(validator.addPreprepareMessage(preprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(preprepareMsg)).isTrue();
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> secondPreprepareMsg = final SignedData<ProposalPayload> secondPreprepareMsg =
proposerMessageFactory.createIbftSignedPrePrepareMessageData(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
assertThat(validator.addPreprepareMessage(secondPreprepareMsg)).isTrue(); assertThat(validator.addSignedProposalPayload(secondPreprepareMsg)).isTrue();
} }
@Test @Test
@ -284,9 +279,9 @@ public class MessageValidatorTest {
insertRoundToBlockHeader(roundIdentifier.getRoundNumber() + 1); insertRoundToBlockHeader(roundIdentifier.getRoundNumber() + 1);
when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true); when(headerValidator.validateHeader(any(), any(), any(), any())).thenReturn(true);
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> preprepareMsg = final SignedData<ProposalPayload> preprepareMsg =
proposerMessageFactory.createIbftSignedPrePrepareMessageData(roundIdentifier, block); proposerMessageFactory.createSignedProposalPayload(roundIdentifier, block);
assertThat(validator.addPreprepareMessage(preprepareMsg)).isFalse(); assertThat(validator.addSignedProposalPayload(preprepareMsg)).isFalse();
} }
} }

@ -21,11 +21,11 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier; import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftMessageFactory; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.MessageFactory;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftPreparedCertificate; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.PreparePayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftSignedMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.PreparedCertificate;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftUnsignedPrepareMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.RoundChangePayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.IbftUnsignedRoundChangeMessageData; import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.SignedData;
import tech.pegasys.pantheon.consensus.ibft.validation.RoundChangeMessageValidator.MessageValidatorFactory; import tech.pegasys.pantheon.consensus.ibft.validation.RoundChangeMessageValidator.MessageValidatorFactory;
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;
@ -46,10 +46,9 @@ public class RoundChangeMessageValidatorTest {
private final KeyPair proposerKey = KeyPair.generate(); private final KeyPair proposerKey = KeyPair.generate();
private final KeyPair validatorKey = KeyPair.generate(); private final KeyPair validatorKey = KeyPair.generate();
private final KeyPair nonValidatorKey = KeyPair.generate(); private final KeyPair nonValidatorKey = KeyPair.generate();
private final IbftMessageFactory proposerMessageFactory = new IbftMessageFactory(proposerKey); private final MessageFactory proposerMessageFactory = new MessageFactory(proposerKey);
private final IbftMessageFactory validatorMessageFactory = new IbftMessageFactory(validatorKey); private final MessageFactory validatorMessageFactory = new MessageFactory(validatorKey);
private final IbftMessageFactory nonValidatorMessageFactory = private final MessageFactory nonValidatorMessageFactory = new MessageFactory(nonValidatorKey);
new IbftMessageFactory(nonValidatorKey);
private final ConsensusRoundIdentifier currentRound = new ConsensusRoundIdentifier(2, 3); private final ConsensusRoundIdentifier currentRound = new ConsensusRoundIdentifier(2, 3);
private final ConsensusRoundIdentifier targetRound = new ConsensusRoundIdentifier(2, 4); private final ConsensusRoundIdentifier targetRound = new ConsensusRoundIdentifier(2, 4);
@ -73,82 +72,76 @@ public class RoundChangeMessageValidatorTest {
// By default, have all basic messages being valid thus any failures are attributed to logic // By default, have all basic messages being valid thus any failures are attributed to logic
// in the RoundChangeMessageValidator // in the RoundChangeMessageValidator
when(basicValidator.addPreprepareMessage(any())).thenReturn(true); when(basicValidator.addSignedProposalPayload(any())).thenReturn(true);
when(basicValidator.validatePrepareMessage(any())).thenReturn(true); when(basicValidator.validatePrepareMessage(any())).thenReturn(true);
} }
@Test @Test
public void roundChangeSentByNonValidatorFails() { public void roundChangeSentByNonValidatorFails() {
final IbftSignedMessageData<IbftUnsignedRoundChangeMessageData> msg = final SignedData<RoundChangePayload> msg =
nonValidatorMessageFactory.createIbftSignedRoundChangeMessageData( nonValidatorMessageFactory.createSignedRoundChangePayload(targetRound, Optional.empty());
targetRound, Optional.empty());
assertThat(validator.validateMessage(msg)).isFalse(); assertThat(validator.validateMessage(msg)).isFalse();
} }
@Test @Test
public void roundChangeContainingNoCertificateIsSuccessful() { public void roundChangeContainingNoCertificateIsSuccessful() {
final IbftSignedMessageData<IbftUnsignedRoundChangeMessageData> msg = final SignedData<RoundChangePayload> msg =
proposerMessageFactory.createIbftSignedRoundChangeMessageData( proposerMessageFactory.createSignedRoundChangePayload(targetRound, Optional.empty());
targetRound, Optional.empty());
assertThat(validator.validateMessage(msg)).isTrue(); assertThat(validator.validateMessage(msg)).isTrue();
} }
@Test @Test
public void roundChangeContainingInvalidPreprepareFails() { public void roundChangeContainingInvalidPreprepareFails() {
final IbftPreparedCertificate prepareCertificate = final PreparedCertificate prepareCertificate =
new IbftPreparedCertificate( new PreparedCertificate(
proposerMessageFactory.createIbftSignedPrePrepareMessageData(currentRound, block), proposerMessageFactory.createSignedProposalPayload(currentRound, block),
Collections.emptyList()); Collections.emptyList());
final IbftSignedMessageData<IbftUnsignedRoundChangeMessageData> msg = final SignedData<RoundChangePayload> msg =
proposerMessageFactory.createIbftSignedRoundChangeMessageData( proposerMessageFactory.createSignedRoundChangePayload(
targetRound, Optional.of(prepareCertificate)); targetRound, Optional.of(prepareCertificate));
when(basicValidator.addPreprepareMessage(any())).thenReturn(false); when(basicValidator.addSignedProposalPayload(any())).thenReturn(false);
assertThat(validator.validateMessage(msg)).isFalse(); assertThat(validator.validateMessage(msg)).isFalse();
verify(validatorFactory, times(1)) verify(validatorFactory, times(1))
.createAt( .createAt(prepareCertificate.getProposalPayload().getPayload().getRoundIdentifier());
prepareCertificate
.getIbftPrePrepareMessage()
.getUnsignedMessageData()
.getRoundIdentifier());
verify(basicValidator, times(1)) verify(basicValidator, times(1))
.addPreprepareMessage(prepareCertificate.getIbftPrePrepareMessage()); .addSignedProposalPayload(prepareCertificate.getProposalPayload());
verify(basicValidator, never()).validatePrepareMessage(any()); verify(basicValidator, never()).validatePrepareMessage(any());
verify(basicValidator, never()).validateCommmitMessage(any()); verify(basicValidator, never()).validateCommmitMessage(any());
} }
@Test @Test
public void roundChangeContainingValidPreprepareButNoPrepareMessagesFails() { public void roundChangeContainingValidPreprepareButNoPrepareMessagesFails() {
final IbftPreparedCertificate prepareCertificate = final PreparedCertificate prepareCertificate =
new IbftPreparedCertificate( new PreparedCertificate(
proposerMessageFactory.createIbftSignedPrePrepareMessageData(currentRound, block), proposerMessageFactory.createSignedProposalPayload(currentRound, block),
Collections.emptyList()); Collections.emptyList());
final IbftSignedMessageData<IbftUnsignedRoundChangeMessageData> msg = final SignedData<RoundChangePayload> msg =
proposerMessageFactory.createIbftSignedRoundChangeMessageData( proposerMessageFactory.createSignedRoundChangePayload(
targetRound, Optional.of(prepareCertificate)); targetRound, Optional.of(prepareCertificate));
when(basicValidator.addPreprepareMessage(any())).thenReturn(true); when(basicValidator.addSignedProposalPayload(any())).thenReturn(true);
assertThat(validator.validateMessage(msg)).isFalse(); assertThat(validator.validateMessage(msg)).isFalse();
} }
@Test @Test
public void roundChangeInvalidPrepareMessageFromProposerFails() { public void roundChangeInvalidPrepareMessageFromProposerFails() {
final IbftSignedMessageData<IbftUnsignedPrepareMessageData> prepareMsg = final SignedData<PreparePayload> prepareMsg =
validatorMessageFactory.createIbftSignedPrepareMessageData(currentRound, block.getHash()); validatorMessageFactory.createSignedPreparePayload(currentRound, block.getHash());
final IbftPreparedCertificate prepareCertificate = final PreparedCertificate prepareCertificate =
new IbftPreparedCertificate( new PreparedCertificate(
proposerMessageFactory.createIbftSignedPrePrepareMessageData(currentRound, block), proposerMessageFactory.createSignedProposalPayload(currentRound, block),
Lists.newArrayList(prepareMsg)); Lists.newArrayList(prepareMsg));
when(basicValidator.addPreprepareMessage(any())).thenReturn(true); when(basicValidator.addSignedProposalPayload(any())).thenReturn(true);
when(basicValidator.validatePrepareMessage(any())).thenReturn(false); when(basicValidator.validatePrepareMessage(any())).thenReturn(false);
final IbftSignedMessageData<IbftUnsignedRoundChangeMessageData> msg = final SignedData<RoundChangePayload> msg =
proposerMessageFactory.createIbftSignedRoundChangeMessageData( proposerMessageFactory.createSignedRoundChangePayload(
targetRound, Optional.of(prepareCertificate)); targetRound, Optional.of(prepareCertificate));
assertThat(validator.validateMessage(msg)).isFalse(); assertThat(validator.validateMessage(msg)).isFalse();
@ -162,8 +155,8 @@ public class RoundChangeMessageValidatorTest {
final ConsensusRoundIdentifier latterRoundIdentifier = final ConsensusRoundIdentifier latterRoundIdentifier =
new ConsensusRoundIdentifier(currentRound.getSequenceNumber() + 1, 1); new ConsensusRoundIdentifier(currentRound.getSequenceNumber() + 1, 1);
final IbftSignedMessageData<IbftUnsignedRoundChangeMessageData> msg = final SignedData<RoundChangePayload> msg =
proposerMessageFactory.createIbftSignedRoundChangeMessageData( proposerMessageFactory.createSignedRoundChangePayload(
latterRoundIdentifier, Optional.empty()); latterRoundIdentifier, Optional.empty());
assertThat(validator.validateMessage(msg)).isFalse(); assertThat(validator.validateMessage(msg)).isFalse();
@ -176,15 +169,15 @@ public class RoundChangeMessageValidatorTest {
new ConsensusRoundIdentifier( new ConsensusRoundIdentifier(
currentRound.getSequenceNumber(), currentRound.getRoundNumber() + 2); currentRound.getSequenceNumber(), currentRound.getRoundNumber() + 2);
final IbftSignedMessageData<IbftUnsignedPrepareMessageData> prepareMsg = final SignedData<PreparePayload> prepareMsg =
validatorMessageFactory.createIbftSignedPrepareMessageData(futureRound, block.getHash()); validatorMessageFactory.createSignedPreparePayload(futureRound, block.getHash());
final IbftPreparedCertificate prepareCertificate = final PreparedCertificate prepareCertificate =
new IbftPreparedCertificate( new PreparedCertificate(
proposerMessageFactory.createIbftSignedPrePrepareMessageData(futureRound, block), proposerMessageFactory.createSignedProposalPayload(futureRound, block),
Lists.newArrayList(prepareMsg)); Lists.newArrayList(prepareMsg));
final IbftSignedMessageData<IbftUnsignedRoundChangeMessageData> msg = final SignedData<RoundChangePayload> msg =
proposerMessageFactory.createIbftSignedRoundChangeMessageData( proposerMessageFactory.createSignedRoundChangePayload(
targetRound, Optional.of(prepareCertificate)); targetRound, Optional.of(prepareCertificate));
assertThat(validator.validateMessage(msg)).isFalse(); assertThat(validator.validateMessage(msg)).isFalse();
@ -195,30 +188,26 @@ public class RoundChangeMessageValidatorTest {
@Test @Test
public void roudnChangeWithPastPreprepareForCurrentHeightIsSuccessful() { public void roudnChangeWithPastPreprepareForCurrentHeightIsSuccessful() {
final IbftSignedMessageData<IbftUnsignedPrepareMessageData> prepareMsg = final SignedData<PreparePayload> prepareMsg =
validatorMessageFactory.createIbftSignedPrepareMessageData(currentRound, block.getHash()); validatorMessageFactory.createSignedPreparePayload(currentRound, block.getHash());
final IbftPreparedCertificate prepareCertificate = final PreparedCertificate prepareCertificate =
new IbftPreparedCertificate( new PreparedCertificate(
proposerMessageFactory.createIbftSignedPrePrepareMessageData(currentRound, block), proposerMessageFactory.createSignedProposalPayload(currentRound, block),
Lists.newArrayList(prepareMsg)); Lists.newArrayList(prepareMsg));
final IbftSignedMessageData<IbftUnsignedRoundChangeMessageData> msg = final SignedData<RoundChangePayload> msg =
proposerMessageFactory.createIbftSignedRoundChangeMessageData( proposerMessageFactory.createSignedRoundChangePayload(
targetRound, Optional.of(prepareCertificate)); targetRound, Optional.of(prepareCertificate));
when(basicValidator.addPreprepareMessage(prepareCertificate.getIbftPrePrepareMessage())) when(basicValidator.addSignedProposalPayload(prepareCertificate.getProposalPayload()))
.thenReturn(true); .thenReturn(true);
when(basicValidator.validatePrepareMessage(prepareMsg)).thenReturn(true); when(basicValidator.validatePrepareMessage(prepareMsg)).thenReturn(true);
assertThat(validator.validateMessage(msg)).isTrue(); assertThat(validator.validateMessage(msg)).isTrue();
verify(validatorFactory, times(1)) verify(validatorFactory, times(1))
.createAt( .createAt(prepareCertificate.getProposalPayload().getPayload().getRoundIdentifier());
prepareCertificate
.getIbftPrePrepareMessage()
.getUnsignedMessageData()
.getRoundIdentifier());
verify(basicValidator, times(1)) verify(basicValidator, times(1))
.addPreprepareMessage(prepareCertificate.getIbftPrePrepareMessage()); .addSignedProposalPayload(prepareCertificate.getProposalPayload());
verify(basicValidator, times(1)).validatePrepareMessage(prepareMsg); verify(basicValidator, times(1)).validatePrepareMessage(prepareMsg);
} }
} }

Loading…
Cancel
Save