Create Qbft Prepare and Commit messages (#1691)

This adds the Prepare and Commit messages used in the QBFT protocol, this is an incremental movement toward QBFT - and does not offer new functionality.

Signed-off-by: Trent Mohay <trent.mohay@consensys.net>
pull/1747/head
Trent Mohay 4 years ago committed by GitHub
parent 2544dfd3e8
commit 6dd89a534a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 71
      consensus/qbft/build.gradle
  2. 48
      consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagedata/CommitMessageData.java
  3. 48
      consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagedata/PrepareMessageData.java
  4. 25
      consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagedata/QbftV1.java
  5. 44
      consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagewrappers/Commit.java
  6. 39
      consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagewrappers/Prepare.java
  7. 107
      consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/CommitPayload.java
  8. 60
      consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/MessageFactory.java
  9. 56
      consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/PayloadDeserializers.java
  10. 92
      consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/PreparePayload.java
  11. 61
      consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/CommitTest.java
  12. 55
      consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/PrepareTest.java
  13. 1
      settings.gradle

@ -0,0 +1,71 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
apply plugin: 'java-library'
jar {
archiveBaseName = 'besu-qbft'
manifest {
attributes(
'Specification-Title': archiveBaseName,
'Specification-Version': project.version,
'Implementation-Title': archiveBaseName,
'Implementation-Version': calculateVersion()
)
}
}
dependencies {
implementation project(':config')
implementation project(':consensus:common')
implementation project(':crypto')
implementation project(':ethereum:api')
implementation project(':ethereum:blockcreation')
implementation project(':ethereum:core')
implementation project(':ethereum:eth')
implementation project(':ethereum:p2p')
implementation project(':ethereum:rlp')
implementation project(':services:kvstore')
implementation 'com.google.guava:guava'
implementation 'io.vertx:vertx-core'
implementation 'org.apache.tuweni:bytes'
implementation 'org.apache.tuweni:units'
integrationTestImplementation project(path: ':config', configuration: 'testSupportArtifacts')
integrationTestImplementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts')
testImplementation 'junit:junit'
testImplementation 'org.awaitility:awaitility'
testImplementation 'org.assertj:assertj-core'
testImplementation 'org.mockito:mockito-core'
testImplementation project(path: ':crypto', configuration: 'testSupportArtifacts')
testImplementation project(path: ':config', configuration: 'testSupportArtifacts')
testImplementation project(path: ':consensus:common', configuration: 'testArtifacts')
testImplementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts')
testImplementation project(':metrics:core')
testImplementation project(':testutil')
testImplementation project(':crypto')
integrationTestImplementation project(path: ':crypto', configuration: 'testSupportArtifacts')
integrationTestImplementation project(':metrics:core')
integrationTestImplementation project(':testutil')
integrationTestImplementation 'junit:junit'
integrationTestImplementation 'org.assertj:assertj-core'
integrationTestImplementation 'org.mockito:mockito-core'
testSupportImplementation 'org.mockito:mockito-core'
}

@ -0,0 +1,48 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.consensus.qbft.messagedata;
import org.hyperledger.besu.consensus.common.bft.messagedata.AbstractBftMessageData;
import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData;
import org.apache.tuweni.bytes.Bytes;
public class CommitMessageData extends AbstractBftMessageData {
private static final int MESSAGE_CODE = QbftV1.COMMIT;
private CommitMessageData(final Bytes data) {
super(data);
}
public static CommitMessageData fromMessageData(final MessageData messageData) {
return fromMessageData(
messageData, MESSAGE_CODE, CommitMessageData.class, CommitMessageData::new);
}
public Commit decode() {
return Commit.decode(data);
}
public static CommitMessageData create(final Commit commit) {
return new CommitMessageData(commit.encode());
}
@Override
public int getCode() {
return MESSAGE_CODE;
}
}

@ -0,0 +1,48 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.consensus.qbft.messagedata;
import org.hyperledger.besu.consensus.common.bft.messagedata.AbstractBftMessageData;
import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData;
import org.apache.tuweni.bytes.Bytes;
public class PrepareMessageData extends AbstractBftMessageData {
private static final int MESSAGE_CODE = QbftV1.PREPARE;
private PrepareMessageData(final Bytes data) {
super(data);
}
public static PrepareMessageData fromMessageData(final MessageData messageData) {
return fromMessageData(
messageData, MESSAGE_CODE, PrepareMessageData.class, PrepareMessageData::new);
}
public Prepare decode() {
return Prepare.decode(data);
}
public static PrepareMessageData create(final Prepare preapare) {
return new PrepareMessageData(preapare.encode());
}
@Override
public int getCode() {
return MESSAGE_CODE;
}
}

@ -0,0 +1,25 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.consensus.qbft.messagedata;
/** Message codes for QBFT v1 messages */
public class QbftV1 {
public static final int PROPOSAL = 0;
public static final int PREPARE = 1;
public static final int COMMIT = 2;
public static final int ROUND_CHANGE = 3;
public static final int MESSAGE_SPACE = 4;
}

@ -0,0 +1,44 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.consensus.qbft.messagewrappers;
import org.hyperledger.besu.consensus.common.bft.messagewrappers.BftMessage;
import org.hyperledger.besu.consensus.common.bft.payload.SignedData;
import org.hyperledger.besu.consensus.qbft.payload.CommitPayload;
import org.hyperledger.besu.consensus.qbft.payload.PayloadDeserializers;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.apache.tuweni.bytes.Bytes;
public class Commit extends BftMessage<CommitPayload> {
public Commit(final SignedData<CommitPayload> payload) {
super(payload);
}
public Signature getCommitSeal() {
return getPayload().getCommitSeal();
}
public Hash getDigest() {
return getPayload().getDigest();
}
public static Commit decode(final Bytes data) {
return new Commit(PayloadDeserializers.readSignedCommitPayloadFrom(RLP.input(data)));
}
}

@ -0,0 +1,39 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.consensus.qbft.messagewrappers;
import org.hyperledger.besu.consensus.common.bft.messagewrappers.BftMessage;
import org.hyperledger.besu.consensus.common.bft.payload.SignedData;
import org.hyperledger.besu.consensus.qbft.payload.PayloadDeserializers;
import org.hyperledger.besu.consensus.qbft.payload.PreparePayload;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.apache.tuweni.bytes.Bytes;
public class Prepare extends BftMessage<PreparePayload> {
public Prepare(final SignedData<PreparePayload> payload) {
super(payload);
}
public Hash getDigest() {
return getPayload().getDigest();
}
public static Prepare decode(final Bytes data) {
return new Prepare(PayloadDeserializers.readSignedPreparePayloadFrom(RLP.input(data)));
}
}

@ -0,0 +1,107 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.consensus.qbft.payload;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.payload.Payload;
import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import java.util.Objects;
import java.util.StringJoiner;
public class CommitPayload implements Payload {
private static final int TYPE = QbftV1.COMMIT;
private final ConsensusRoundIdentifier roundIdentifier;
private final Hash digest;
private final Signature commitSeal;
public CommitPayload(
final ConsensusRoundIdentifier roundIdentifier,
final Hash digest,
final Signature commitSeal) {
this.roundIdentifier = roundIdentifier;
this.digest = digest;
this.commitSeal = commitSeal;
}
public static CommitPayload readFrom(final RLPInput rlpInput) {
rlpInput.enterList();
final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundIdentifier.readFrom(rlpInput);
final Hash digest = Payload.readDigest(rlpInput);
final Signature commitSeal = rlpInput.readBytes(Signature::decode);
rlpInput.leaveList();
return new CommitPayload(roundIdentifier, digest, commitSeal);
}
@Override
public void writeTo(final RLPOutput rlpOutput) {
rlpOutput.startList();
roundIdentifier.writeTo(rlpOutput);
rlpOutput.writeBytes(digest);
rlpOutput.writeBytes(commitSeal.encodedBytes());
rlpOutput.endList();
}
@Override
public int getMessageType() {
return TYPE;
}
public Hash getDigest() {
return digest;
}
public Signature getCommitSeal() {
return commitSeal;
}
@Override
public ConsensusRoundIdentifier getRoundIdentifier() {
return roundIdentifier;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final CommitPayload that = (CommitPayload) o;
return Objects.equals(roundIdentifier, that.roundIdentifier)
&& Objects.equals(digest, that.digest)
&& Objects.equals(commitSeal, that.commitSeal);
}
@Override
public int hashCode() {
return Objects.hash(roundIdentifier, digest, commitSeal);
}
@Override
public String toString() {
return new StringJoiner(", ", CommitPayload.class.getSimpleName() + "[", "]")
.add("roundIdentifier=" + roundIdentifier)
.add("digest=" + digest)
.add("commitSeal=" + commitSeal)
.toString();
}
}

@ -0,0 +1,60 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.consensus.qbft.payload;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.payload.Payload;
import org.hyperledger.besu.consensus.common.bft.payload.SignedData;
import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit;
import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.Util;
import org.apache.tuweni.bytes.Bytes;
public class MessageFactory {
private final NodeKey nodeKey;
public MessageFactory(final NodeKey nodeKey) {
this.nodeKey = nodeKey;
}
public Prepare createPrepare(final ConsensusRoundIdentifier roundIdentifier, final Hash digest) {
final PreparePayload payload = new PreparePayload(roundIdentifier, digest);
return new Prepare(createSignedMessage(payload));
}
public Commit createCommit(
final ConsensusRoundIdentifier roundIdentifier,
final Hash digest,
final Signature commitSeal) {
final CommitPayload payload = new CommitPayload(roundIdentifier, digest, commitSeal);
return new Commit(createSignedMessage(payload));
}
private <M extends Payload> SignedData<M> createSignedMessage(final M payload) {
final Signature signature = nodeKey.sign(hashForSignature(payload));
return new SignedData<>(payload, Util.publicKeyToAddress(nodeKey.getPublicKey()), signature);
}
public static Hash hashForSignature(final Payload unsignedMessageData) {
return Hash.hash(
Bytes.concatenate(
Bytes.of(unsignedMessageData.getMessageType()), unsignedMessageData.encoded()));
}
}

@ -0,0 +1,56 @@
/*
* Copyright 2020 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.consensus.qbft.payload;
import org.hyperledger.besu.consensus.common.bft.payload.Payload;
import org.hyperledger.besu.consensus.common.bft.payload.SignedData;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Util;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
public class PayloadDeserializers {
public static SignedData<PreparePayload> readSignedPreparePayloadFrom(final RLPInput rlpInput) {
rlpInput.enterList();
final PreparePayload unsignedMessageData = PreparePayload.readFrom(rlpInput);
final Signature signature = readSignature(rlpInput);
rlpInput.leaveList();
return from(unsignedMessageData, signature);
}
public static SignedData<CommitPayload> readSignedCommitPayloadFrom(final RLPInput rlpInput) {
rlpInput.enterList();
final CommitPayload unsignedMessageData = CommitPayload.readFrom(rlpInput);
final Signature signature = readSignature(rlpInput);
rlpInput.leaveList();
return from(unsignedMessageData, signature);
}
protected static <M extends Payload> SignedData<M> from(
final M unsignedMessageData, final Signature signature) {
final Address sender = recoverSender(unsignedMessageData, signature);
return new SignedData<>(unsignedMessageData, sender, signature);
}
protected static Signature readSignature(final RLPInput signedMessage) {
return signedMessage.readBytes(Signature::decode);
}
protected static Address recoverSender(
final Payload unsignedMessageData, final Signature signature) {
return Util.signatureToAddress(signature, MessageFactory.hashForSignature(unsignedMessageData));
}
}

@ -0,0 +1,92 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.consensus.qbft.payload;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.payload.Payload;
import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import java.util.Objects;
import java.util.StringJoiner;
public class PreparePayload implements Payload {
private static final int TYPE = QbftV1.PREPARE;
private final ConsensusRoundIdentifier roundIdentifier;
private final Hash digest;
public PreparePayload(final ConsensusRoundIdentifier roundIdentifier, final Hash digest) {
this.roundIdentifier = roundIdentifier;
this.digest = digest;
}
public static PreparePayload readFrom(final RLPInput rlpInput) {
rlpInput.enterList();
final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundIdentifier.readFrom(rlpInput);
final Hash digest = Payload.readDigest(rlpInput);
rlpInput.leaveList();
return new PreparePayload(roundIdentifier, digest);
}
@Override
public void writeTo(final RLPOutput rlpOutput) {
rlpOutput.startList();
roundIdentifier.writeTo(rlpOutput);
rlpOutput.writeBytes(digest);
rlpOutput.endList();
}
@Override
public int getMessageType() {
return TYPE;
}
public Hash getDigest() {
return digest;
}
@Override
public ConsensusRoundIdentifier getRoundIdentifier() {
return roundIdentifier;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final PreparePayload that = (PreparePayload) o;
return Objects.equals(roundIdentifier, that.roundIdentifier)
&& Objects.equals(digest, that.digest);
}
@Override
public int hashCode() {
return Objects.hash(roundIdentifier, digest);
}
@Override
public String toString() {
return new StringJoiner(", ", PreparePayload.class.getSimpleName() + "[", "]")
.add("roundIdentifier=" + roundIdentifier)
.add("digest=" + digest)
.toString();
}
}

@ -0,0 +1,61 @@
/*
* Copyright 2020 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.consensus.qbft.messagewrappers;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.payload.SignedData;
import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1;
import org.hyperledger.besu.consensus.qbft.payload.CommitPayload;
import org.hyperledger.besu.consensus.qbft.payload.MessageFactory;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.Util;
import java.math.BigInteger;
import org.junit.Test;
public class CommitTest {
@Test
public void canRoundTripAPrepareMessage() {
final NodeKey nodeKey = NodeKeyUtils.generate();
final Address addr = Util.publicKeyToAddress(nodeKey.getPublicKey());
final CommitPayload commitPayload =
new CommitPayload(
new ConsensusRoundIdentifier(1, 1),
Hash.ZERO,
Signature.create(BigInteger.ONE, BigInteger.ONE, (byte) 0));
final SignedData<CommitPayload> signedCommitPayload =
new SignedData<>(
commitPayload, addr, nodeKey.sign(MessageFactory.hashForSignature(commitPayload)));
final Commit commitMsg = new Commit(signedCommitPayload);
final Commit decodedPrepare = Commit.decode(commitMsg.encode());
assertThat(decodedPrepare.getMessageType()).isEqualTo(QbftV1.COMMIT);
assertThat(decodedPrepare.getAuthor()).isEqualTo(addr);
assertThat(decodedPrepare.getSignedPayload())
.isEqualToComparingFieldByField(signedCommitPayload);
}
}

@ -0,0 +1,55 @@
/*
* Copyright 2020 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.consensus.qbft.messagewrappers;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.payload.SignedData;
import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1;
import org.hyperledger.besu.consensus.qbft.payload.MessageFactory;
import org.hyperledger.besu.consensus.qbft.payload.PreparePayload;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.Util;
import org.junit.Test;
public class PrepareTest {
@Test
public void canRoundTripAPrepareMessage() {
final NodeKey nodeKey = NodeKeyUtils.generate();
final Address addr = Util.publicKeyToAddress(nodeKey.getPublicKey());
final PreparePayload preparePayload =
new PreparePayload(new ConsensusRoundIdentifier(1, 1), Hash.ZERO);
final SignedData<PreparePayload> signedPreparePayload =
new SignedData<>(
preparePayload, addr, nodeKey.sign(MessageFactory.hashForSignature(preparePayload)));
final Prepare prepareMsg = new Prepare(signedPreparePayload);
final Prepare decodedPrepare = Prepare.decode(prepareMsg.encode());
assertThat(decodedPrepare.getMessageType()).isEqualTo(QbftV1.PREPARE);
assertThat(decodedPrepare.getAuthor()).isEqualTo(addr);
assertThat(decodedPrepare.getSignedPayload())
.isEqualToComparingFieldByField(signedPreparePayload);
}
}

@ -22,6 +22,7 @@ include 'consensus:clique'
include 'consensus:common'
include 'consensus:ibft'
include 'consensus:ibftlegacy'
include 'consensus:qbft'
include 'crypto'
include 'enclave'
include 'errorprone-checks'

Loading…
Cancel
Save