mirror of
https://github.com/vacp2p/linea-besu.git
synced 2026-01-09 15:37:54 -05:00
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>
This commit is contained in:
71
consensus/qbft/build.gradle
Normal file
71
consensus/qbft/build.gradle
Normal file
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user