[EC-183] Added RLP enc/dec for PrePrepare, Commit and NewRound messages (#200)

Roberto Saltini 6 years ago committed by GitHub
parent 448e465f3f
commit 14a8f3780a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftMessages.java
  2. 22
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/AbstractIbftMessage.java
  3. 48
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/IbftCommitMessage.java
  4. 48
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/IbftNewRoundMessage.java
  5. 12
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/IbftPrePrepareMessage.java
  6. 11
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/IbftPrepareMessage.java
  7. 12
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/IbftRoundChangeMessage.java
  8. 3
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/IbftV2.java
  9. 36
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/IbftMessageFactory.java
  10. 9
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/IbftPreparedCertificate.java
  11. 53
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/IbftRoundChangeCertificate.java
  12. 24
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/IbftSignedMessageData.java
  13. 69
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/IbftUnsignedCommitMessageData.java
  14. 79
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/IbftUnsignedNewRoundMessageData.java
  15. 34
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftmessagedata/IbftUnsignedPrePrepareMessageData.java
  16. 1
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/protocol/IbftSubProtocol.java
  17. 5
      consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/protocol/IbftSubProtocolTest.java

@ -12,6 +12,8 @@
*/ */
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.IbftNewRoundMessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessage.IbftPrePrepareMessage; import tech.pegasys.pantheon.consensus.ibft.ibftmessage.IbftPrePrepareMessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessage.IbftPrepareMessage; import tech.pegasys.pantheon.consensus.ibft.ibftmessage.IbftPrepareMessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessage.IbftRoundChangeMessage; import tech.pegasys.pantheon.consensus.ibft.ibftmessage.IbftRoundChangeMessage;
@ -32,9 +34,15 @@ public class IbftMessages {
case IbftV2.PREPARE: case IbftV2.PREPARE:
return IbftPrepareMessage.fromMessage(messageData).decode(); return IbftPrepareMessage.fromMessage(messageData).decode();
case IbftV2.COMMIT:
return IbftCommitMessage.fromMessage(messageData).decode();
case IbftV2.ROUND_CHANGE: case IbftV2.ROUND_CHANGE:
return IbftRoundChangeMessage.fromMessage(messageData).decode(); return IbftRoundChangeMessage.fromMessage(messageData).decode();
case IbftV2.NEW_ROUND:
return IbftNewRoundMessage.fromMessage(messageData).decode();
default: default:
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Received message does not conform to any recognised IBFT message structure."); "Received message does not conform to any recognised IBFT message structure.");

@ -13,13 +13,35 @@
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.IbftSignedMessageData;
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;
import java.util.function.Function;
public abstract class AbstractIbftMessage extends AbstractMessageData { public abstract class AbstractIbftMessage extends AbstractMessageData {
protected AbstractIbftMessage(final BytesValue data) { protected AbstractIbftMessage(final BytesValue data) {
super(data); super(data);
} }
public abstract IbftSignedMessageData<?> decode(); public abstract IbftSignedMessageData<?> decode();
protected static <T extends AbstractIbftMessage> T fromMessage(
final MessageData message,
final int messageCode,
final Class<T> clazz,
final Function<BytesValue, T> constructor) {
if (clazz.isInstance(message)) {
@SuppressWarnings("unchecked")
T castMessage = (T) message;
return castMessage;
}
final int code = message.getCode();
if (code != messageCode) {
throw new IllegalArgumentException(
String.format("Message has code %d and thus is not a %s", code, clazz.getSimpleName()));
}
return constructor.apply(message.getData());
}
} }

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

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

@ -27,16 +27,8 @@ public class IbftPrePrepareMessage extends AbstractIbftMessage {
} }
public static IbftPrePrepareMessage fromMessage(final MessageData message) { public static IbftPrePrepareMessage fromMessage(final MessageData message) {
if (message instanceof IbftPrePrepareMessage) { return fromMessage(
return (IbftPrePrepareMessage) message; message, MESSAGE_CODE, IbftPrePrepareMessage.class, IbftPrePrepareMessage::new);
}
final int code = message.getCode();
if (code != MESSAGE_CODE) {
throw new IllegalArgumentException(
String.format("Message has code %d and thus is not a PrePrepareMessage", code));
}
return new IbftPrePrepareMessage(message.getData());
} }
@Override @Override

@ -27,16 +27,7 @@ public class IbftPrepareMessage extends AbstractIbftMessage {
} }
public static IbftPrepareMessage fromMessage(final MessageData message) { public static IbftPrepareMessage fromMessage(final MessageData message) {
if (message instanceof IbftPrepareMessage) { return fromMessage(message, MESSAGE_CODE, IbftPrepareMessage.class, IbftPrepareMessage::new);
return (IbftPrepareMessage) message;
}
final int code = message.getCode();
if (code != MESSAGE_CODE) {
throw new IllegalArgumentException(
String.format("Message has code %d and thus is not a PrepareMessage", code));
}
return new IbftPrepareMessage(message.getData());
} }
@Override @Override

@ -27,16 +27,8 @@ public class IbftRoundChangeMessage extends AbstractIbftMessage {
} }
public static IbftRoundChangeMessage fromMessage(final MessageData message) { public static IbftRoundChangeMessage fromMessage(final MessageData message) {
if (message instanceof IbftRoundChangeMessage) { return fromMessage(
return (IbftRoundChangeMessage) message; message, MESSAGE_CODE, IbftRoundChangeMessage.class, IbftRoundChangeMessage::new);
}
final int code = message.getCode();
if (code != MESSAGE_CODE) {
throw new IllegalArgumentException(
String.format("Message has code %d and thus is not a RoundChangeMessage", code));
}
return new IbftRoundChangeMessage(message.getData());
} }
@Override @Override

@ -18,6 +18,7 @@ public class IbftV2 {
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;
public static final int NEW_ROUND = 4;
public static final int MESSAGE_SPACE = 4; public static final int MESSAGE_SPACE = 5;
} }

@ -16,6 +16,7 @@ import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
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.crypto.SECP256K1.Signature; 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.Hash;
import tech.pegasys.pantheon.ethereum.core.Util; import tech.pegasys.pantheon.ethereum.core.Util;
import tech.pegasys.pantheon.util.bytes.BytesValues; import tech.pegasys.pantheon.util.bytes.BytesValues;
@ -29,6 +30,16 @@ public class IbftMessageFactory {
this.validatorKeyPair = 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( public IbftSignedMessageData<IbftUnsignedPrepareMessageData> createIbftSignedPrepareMessageData(
final ConsensusRoundIdentifier roundIdentifier, final Hash digest) { final ConsensusRoundIdentifier roundIdentifier, final Hash digest) {
@ -38,6 +49,17 @@ public class IbftMessageFactory {
return createSignedMessage(prepareUnsignedMessageData); 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> public IbftSignedMessageData<IbftUnsignedRoundChangeMessageData>
createIbftSignedRoundChangeMessageData( createIbftSignedRoundChangeMessageData(
final ConsensusRoundIdentifier roundIdentifier, final ConsensusRoundIdentifier roundIdentifier,
@ -49,6 +71,20 @@ public class IbftMessageFactory {
return createSignedMessage(prepareUnsignedMessageData); 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( private <M extends AbstractIbftUnsignedMessageData> IbftSignedMessageData<M> createSignedMessage(
final M ibftUnsignedMessage) { final M ibftUnsignedMessage) {
final Signature signature = sign(ibftUnsignedMessage, validatorKeyPair); final Signature signature = sign(ibftUnsignedMessage, validatorKeyPair);

@ -50,4 +50,13 @@ public class IbftPreparedCertificate {
rlpOutput.writeList(ibftPrepareMessages, IbftSignedMessageData::writeTo); rlpOutput.writeList(ibftPrepareMessages, IbftSignedMessageData::writeTo);
rlpOutput.endList(); rlpOutput.endList();
} }
public IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> getIbftPrePrepareMessage() {
return ibftPrePrepareMessage;
}
public Collection<IbftSignedMessageData<IbftUnsignedPrepareMessageData>>
getIbftPrepareMessages() {
return ibftPrepareMessages;
}
} }

@ -0,0 +1,53 @@
/*
* 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;
}
}

@ -83,6 +83,18 @@ public class IbftSignedMessageData<M extends AbstractIbftUnsignedMessageData> {
return from(unsignedMessageData, signature); return from(unsignedMessageData, signature);
} }
public static IbftSignedMessageData<IbftUnsignedCommitMessageData>
readIbftSignedCommitMessageDataFrom(final RLPInput rlpInput) {
rlpInput.enterList();
final IbftUnsignedCommitMessageData unsignedMessageData =
IbftUnsignedCommitMessageData.readFrom(rlpInput);
final Signature signature = readSignature(rlpInput);
rlpInput.leaveList();
return from(unsignedMessageData, signature);
}
public static IbftSignedMessageData<IbftUnsignedRoundChangeMessageData> public static IbftSignedMessageData<IbftUnsignedRoundChangeMessageData>
readIbftSignedRoundChangeMessageDataFrom(final RLPInput rlpInput) { readIbftSignedRoundChangeMessageDataFrom(final RLPInput rlpInput) {
@ -95,6 +107,18 @@ public class IbftSignedMessageData<M extends AbstractIbftUnsignedMessageData> {
return from(unsignedMessageData, signature); return from(unsignedMessageData, signature);
} }
public static IbftSignedMessageData<IbftUnsignedNewRoundMessageData>
readIbftSignedNewRoundMessageDataFrom(final RLPInput rlpInput) {
rlpInput.enterList();
final IbftUnsignedNewRoundMessageData unsignedMessageData =
IbftUnsignedNewRoundMessageData.readFrom(rlpInput);
final Signature signature = readSignature(rlpInput);
rlpInput.leaveList();
return from(unsignedMessageData, signature);
}
protected static <M extends AbstractIbftUnsignedMessageData> IbftSignedMessageData<M> from( protected static <M extends AbstractIbftUnsignedMessageData> IbftSignedMessageData<M> from(
final M unsignedMessageData, final Signature signature) { final M unsignedMessageData, final Signature signature) {

@ -0,0 +1,69 @@
/*
* 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.consensus.ibft.ibftmessage.IbftV2;
import tech.pegasys.pantheon.crypto.SECP256K1.Signature;
import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
public class IbftUnsignedCommitMessageData extends AbstractIbftUnsignedInRoundMessageData {
private static final int TYPE = IbftV2.COMMIT;
private final Hash digest;
private final Signature commitSeal;
public IbftUnsignedCommitMessageData(
final ConsensusRoundIdentifier roundIdentifier,
final Hash digest,
final Signature commitSeal) {
super(roundIdentifier);
this.digest = digest;
this.commitSeal = commitSeal;
}
public static IbftUnsignedCommitMessageData readFrom(final RLPInput rlpInput) {
rlpInput.enterList();
final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundIdentifier.readFrom(rlpInput);
final Hash digest = readDigest(rlpInput);
final Signature commitSeal = rlpInput.readBytesValue(Signature::decode);
rlpInput.leaveList();
return new IbftUnsignedCommitMessageData(roundIdentifier, digest, commitSeal);
}
@Override
public void writeTo(final RLPOutput rlpOutput) {
rlpOutput.startList();
roundIdentifier.writeTo(rlpOutput);
rlpOutput.writeBytesValue(digest);
rlpOutput.writeBytesValue(commitSeal.encodedBytes());
rlpOutput.endList();
}
@Override
public int getMessageType() {
return TYPE;
}
public Hash getDigest() {
return digest;
}
public Signature getCommitSeal() {
return commitSeal;
}
}

@ -0,0 +1,79 @@
/*
* 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.consensus.ibft.ibftmessage.IbftV2;
import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
public class IbftUnsignedNewRoundMessageData extends AbstractIbftUnsignedMessageData {
private static final int TYPE = IbftV2.NEW_ROUND;
private final ConsensusRoundIdentifier roundChangeIdentifier;
private final IbftRoundChangeCertificate roundChangeCertificate;
private final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> ibftPrePrepareMessage;
public IbftUnsignedNewRoundMessageData(
final ConsensusRoundIdentifier roundIdentifier,
final IbftRoundChangeCertificate roundChangeCertificate,
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> ibftPrePrepareMessage) {
this.roundChangeIdentifier = roundIdentifier;
this.roundChangeCertificate = roundChangeCertificate;
this.ibftPrePrepareMessage = ibftPrePrepareMessage;
}
public ConsensusRoundIdentifier getRoundChangeIdentifier() {
return roundChangeIdentifier;
}
public IbftRoundChangeCertificate getRoundChangeCertificate() {
return roundChangeCertificate;
}
public IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> getIbftPrePrepareMessage() {
return ibftPrePrepareMessage;
}
@Override
public void writeTo(final RLPOutput rlpOutput) {
// RLP encode of the message data content (round identifier and prepared certificate)
rlpOutput.startList();
roundChangeIdentifier.writeTo(rlpOutput);
roundChangeCertificate.writeTo(rlpOutput);
ibftPrePrepareMessage.writeTo(rlpOutput);
rlpOutput.endList();
}
public static IbftUnsignedNewRoundMessageData readFrom(final RLPInput rlpInput) {
rlpInput.enterList();
final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundIdentifier.readFrom(rlpInput);
final IbftRoundChangeCertificate roundChangeCertificate =
IbftRoundChangeCertificate.readFrom(rlpInput);
final IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> ibftPrePrepareMessage =
IbftSignedMessageData.readIbftSignedPrePrepareMessageDataFrom(rlpInput);
rlpInput.leaveList();
return new IbftUnsignedNewRoundMessageData(
roundIdentifier, roundChangeCertificate, ibftPrePrepareMessage);
}
@Override
public int getMessageType() {
return TYPE;
}
}

@ -13,6 +13,8 @@
package tech.pegasys.pantheon.consensus.ibft.ibftmessagedata; package tech.pegasys.pantheon.consensus.ibft.ibftmessagedata;
import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier; import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibft.IbftBlockHashing;
import tech.pegasys.pantheon.consensus.ibft.ibftmessage.IbftV2;
import tech.pegasys.pantheon.ethereum.core.Block; 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;
@ -21,24 +23,40 @@ import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
// how a PreparedCertificate is encoded and decoded inside a RoundChange message // how a PreparedCertificate is encoded and decoded inside a RoundChange message
public class IbftUnsignedPrePrepareMessageData extends AbstractIbftUnsignedInRoundMessageData { public class IbftUnsignedPrePrepareMessageData extends AbstractIbftUnsignedInRoundMessageData {
private static final int TYPE = IbftV2.PRE_PREPARE;
private final Block block;
public IbftUnsignedPrePrepareMessageData( public IbftUnsignedPrePrepareMessageData(
final ConsensusRoundIdentifier roundIdentifier, final Block block) { final ConsensusRoundIdentifier roundIdentifier, final Block block) {
super(roundIdentifier); super(roundIdentifier);
this.block = block;
} }
public Block getBlock() { public static IbftUnsignedPrePrepareMessageData readFrom(final RLPInput rlpInput) {
return null;
rlpInput.enterList();
final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundIdentifier.readFrom(rlpInput);
final Block block = Block.readFrom(rlpInput, IbftBlockHashing::calculateHashOfIbftBlockOnChain);
rlpInput.leaveList();
return new IbftUnsignedPrePrepareMessageData(roundIdentifier, block);
} }
@Override @Override
public void writeTo(final RLPOutput rlpOutput) {} public void writeTo(final RLPOutput rlpOutput) {
@Override rlpOutput.startList();
public int getMessageType() { roundIdentifier.writeTo(rlpOutput);
return 0; block.writeTo(rlpOutput);
rlpOutput.endList();
} }
public static IbftUnsignedPrePrepareMessageData readFrom(final RLPInput rlpInput) { public Block getBlock() {
return null; return block;
}
@Override
public int getMessageType() {
return TYPE;
} }
} }

@ -44,6 +44,7 @@ public class IbftSubProtocol implements SubProtocol {
case IbftV2.PREPARE: case IbftV2.PREPARE:
case IbftV2.COMMIT: case IbftV2.COMMIT:
case IbftV2.ROUND_CHANGE: case IbftV2.ROUND_CHANGE:
case IbftV2.NEW_ROUND:
return true; return true;
default: default:

@ -22,7 +22,7 @@ public class IbftSubProtocolTest {
public void messageSpaceReportsCorrectly() { public void messageSpaceReportsCorrectly() {
final IbftSubProtocol subProt = new IbftSubProtocol(); final IbftSubProtocol subProt = new IbftSubProtocol();
assertThat(subProt.messageSpace(1)).isEqualTo(4); assertThat(subProt.messageSpace(1)).isEqualTo(5);
} }
@Test @Test
@ -33,12 +33,13 @@ public class IbftSubProtocolTest {
assertThat(subProt.isValidMessageCode(1, 1)).isTrue(); assertThat(subProt.isValidMessageCode(1, 1)).isTrue();
assertThat(subProt.isValidMessageCode(1, 2)).isTrue(); assertThat(subProt.isValidMessageCode(1, 2)).isTrue();
assertThat(subProt.isValidMessageCode(1, 3)).isTrue(); assertThat(subProt.isValidMessageCode(1, 3)).isTrue();
assertThat(subProt.isValidMessageCode(1, 4)).isTrue();
} }
@Test @Test
public void invalidMessageTypesAreNotAcceptedByTheSubprotocol() { public void invalidMessageTypesAreNotAcceptedByTheSubprotocol() {
final IbftSubProtocol subProt = new IbftSubProtocol(); final IbftSubProtocol subProt = new IbftSubProtocol();
assertThat(subProt.isValidMessageCode(1, 4)).isFalse(); assertThat(subProt.isValidMessageCode(1, 5)).isFalse();
} }
} }

Loading…
Cancel
Save