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

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

Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
*/
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.IbftPrepareMessage;
import tech.pegasys.pantheon.consensus.ibft.ibftmessage.IbftRoundChangeMessage;
Expand All @@ -32,9 +34,15 @@ public static IbftSignedMessageData<?> fromMessage(final Message message) {
case IbftV2.PREPARE:
return IbftPrepareMessage.fromMessage(messageData).decode();

case IbftV2.COMMIT:
return IbftCommitMessage.fromMessage(messageData).decode();

case IbftV2.ROUND_CHANGE:
return IbftRoundChangeMessage.fromMessage(messageData).decode();

case IbftV2.NEW_ROUND:
return IbftNewRoundMessage.fromMessage(messageData).decode();

default:
throw new IllegalArgumentException(
"Received message does not conform to any recognised IBFT message structure.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,35 @@
package tech.pegasys.pantheon.consensus.ibft.ibftmessage;

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.util.bytes.BytesValue;

import java.util.function.Function;

public abstract class AbstractIbftMessage extends AbstractMessageData {
protected AbstractIbftMessage(final BytesValue data) {
super(data);
}

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());
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,8 @@ private IbftPrePrepareMessage(final BytesValue data) {
}

public static IbftPrePrepareMessage fromMessage(final MessageData message) {
if (message instanceof IbftPrePrepareMessage) {
return (IbftPrePrepareMessage) message;
}
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());
return fromMessage(
message, MESSAGE_CODE, IbftPrePrepareMessage.class, IbftPrePrepareMessage::new);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,7 @@ private IbftPrepareMessage(final BytesValue data) {
}

public static IbftPrepareMessage fromMessage(final MessageData message) {
if (message instanceof IbftPrepareMessage) {
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());
return fromMessage(message, MESSAGE_CODE, IbftPrepareMessage.class, IbftPrepareMessage::new);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,8 @@ private IbftRoundChangeMessage(final BytesValue data) {
}

public static IbftRoundChangeMessage fromMessage(final MessageData message) {
if (message instanceof IbftRoundChangeMessage) {
return (IbftRoundChangeMessage) message;
}
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());
return fromMessage(
message, MESSAGE_CODE, IbftRoundChangeMessage.class, IbftRoundChangeMessage::new);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class IbftV2 {
public static final int PREPARE = 1;
public static final int COMMIT = 2;
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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
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;
Expand All @@ -29,6 +30,16 @@ 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) {

Expand All @@ -38,6 +49,17 @@ public IbftSignedMessageData<IbftUnsignedPrepareMessageData> createIbftSignedPre
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,
Expand All @@ -49,6 +71,20 @@ public IbftSignedMessageData<IbftUnsignedPrepareMessageData> createIbftSignedPre
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,13 @@ public void writeTo(final RLPOutput rlpOutput) {
rlpOutput.writeList(ibftPrepareMessages, IbftSignedMessageData::writeTo);
rlpOutput.endList();
}

public IbftSignedMessageData<IbftUnsignedPrePrepareMessageData> getIbftPrePrepareMessage() {
return ibftPrePrepareMessage;
}

public Collection<IbftSignedMessageData<IbftUnsignedPrepareMessageData>>
getIbftPrepareMessages() {
return ibftPrepareMessages;
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,18 @@ public BytesValue encode() {
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>
readIbftSignedRoundChangeMessageDataFrom(final RLPInput rlpInput) {

Expand All @@ -95,6 +107,18 @@ public BytesValue encode() {
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(
final M unsignedMessageData, final Signature signature) {

Expand Down
Loading