newRoundMsg =
- NewRoundMessage.fromMessage(messageData).decode();
- if (processMessage(newRoundMsg, messageData)) {
- currentHeightManager.handleNewRoundMessage(newRoundMsg);
- }
+ consumeMessage(
+ message,
+ NewRoundMessageData.fromMessageData(messageData).decode(),
+ currentHeightManager::handleNewRoundPayload);
break;
default:
@@ -127,6 +130,16 @@ public class IbftController {
}
}
+ private void consumeMessage(
+ final Message message,
+ final SignedData
signedPayload,
+ final Consumer> handleMessage) {
+ if (processMessage(signedPayload, message)) {
+ gossiper.gossipMessage(message);
+ handleMessage.accept(signedPayload);
+ }
+ }
+
public void handleNewBlockEvent(final NewChainHead newChainHead) {
startNewHeightManager(newChainHead.getNewChainHeadHeader());
}
@@ -151,20 +164,19 @@ public class IbftController {
currentHeightManager = ibftBlockHeightManagerFactory.create(parentHeader);
currentHeightManager.start();
final long newChainHeight = currentHeightManager.getChainHeight();
- List orDefault = futureMessages.getOrDefault(newChainHeight, emptyList());
+ final List orDefault = futureMessages.getOrDefault(newChainHeight, emptyList());
orDefault.forEach(this::handleMessage);
futureMessages.remove(newChainHeight);
}
- private boolean processMessage(
- final SignedData extends Payload> msg, final MessageData rawMsg) {
+ private boolean processMessage(final SignedData extends Payload> msg, final Message rawMsg) {
final ConsensusRoundIdentifier msgRoundIdentifier = msg.getPayload().getRoundIdentifier();
if (isMsgForCurrentHeight(msgRoundIdentifier)) {
return isMsgFromKnownValidator(msg);
} else if (isMsgForFutureChainHeight(msgRoundIdentifier)) {
addMessageToFutureMessageBuffer(msgRoundIdentifier.getSequenceNumber(), rawMsg);
} else {
- LOG.info("IBFT message discarded as it is not for the current block height");
+ LOG.info("IBFT message discarded as it is from a previous block height");
}
return false;
}
@@ -181,7 +193,7 @@ public class IbftController {
return roundIdentifier.getSequenceNumber() > currentHeightManager.getChainHeight();
}
- private void addMessageToFutureMessageBuffer(final long chainHeight, final MessageData rawMsg) {
+ private void addMessageToFutureMessageBuffer(final long chainHeight, final Message rawMsg) {
if (!futureMessages.containsKey(chainHeight)) {
futureMessages.put(chainHeight, Lists.newArrayList());
}
diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftMessageTransmitter.java b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftMessageTransmitter.java
index 4649df1920..6548ead145 100644
--- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftMessageTransmitter.java
+++ b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftMessageTransmitter.java
@@ -13,11 +13,11 @@
package tech.pegasys.pantheon.consensus.ibft.statemachine;
import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
-import tech.pegasys.pantheon.consensus.ibft.ibftmessage.CommitMessage;
-import tech.pegasys.pantheon.consensus.ibft.ibftmessage.NewRoundMessage;
-import tech.pegasys.pantheon.consensus.ibft.ibftmessage.PrepareMessage;
-import tech.pegasys.pantheon.consensus.ibft.ibftmessage.ProposalMessage;
-import tech.pegasys.pantheon.consensus.ibft.ibftmessage.RoundChangeMessage;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessage.CommitMessageData;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessage.NewRoundMessageData;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessage.PrepareMessageData;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessage.ProposalMessageData;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessage.RoundChangeMessageData;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.CommitPayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.MessageFactory;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.NewRoundPayload;
@@ -49,7 +49,7 @@ public class IbftMessageTransmitter {
final SignedData signedPayload =
messageFactory.createSignedProposalPayload(roundIdentifier, block);
- final ProposalMessage message = ProposalMessage.create(signedPayload);
+ final ProposalMessageData message = ProposalMessageData.create(signedPayload);
multicaster.multicastToValidators(message);
}
@@ -58,7 +58,7 @@ public class IbftMessageTransmitter {
final SignedData signedPayload =
messageFactory.createSignedPreparePayload(roundIdentifier, digest);
- final PrepareMessage message = PrepareMessage.create(signedPayload);
+ final PrepareMessageData message = PrepareMessageData.create(signedPayload);
multicaster.multicastToValidators(message);
}
@@ -70,7 +70,7 @@ public class IbftMessageTransmitter {
final SignedData signedPayload =
messageFactory.createSignedCommitPayload(roundIdentifier, digest, commitSeal);
- final CommitMessage message = CommitMessage.create(signedPayload);
+ final CommitMessageData message = CommitMessageData.create(signedPayload);
multicaster.multicastToValidators(message);
}
@@ -82,7 +82,7 @@ public class IbftMessageTransmitter {
final SignedData signedPayload =
messageFactory.createSignedRoundChangePayload(roundIdentifier, preparedCertificate);
- final RoundChangeMessage message = RoundChangeMessage.create(signedPayload);
+ final RoundChangeMessageData message = RoundChangeMessageData.create(signedPayload);
multicaster.multicastToValidators(message);
}
@@ -96,7 +96,7 @@ public class IbftMessageTransmitter {
messageFactory.createSignedNewRoundPayload(
roundIdentifier, roundChangeCertificate, proposalPayload);
- final NewRoundMessage message = NewRoundMessage.create(signedPayload);
+ final NewRoundMessageData message = NewRoundMessageData.create(signedPayload);
multicaster.multicastToValidators(message);
}
diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftGossipTest.java b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftGossipTest.java
new file mode 100644
index 0000000000..b1b366444c
--- /dev/null
+++ b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftGossipTest.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2019 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;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import tech.pegasys.pantheon.consensus.ibft.ibftmessage.CommitMessageData;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessage.NewRoundMessageData;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessage.PrepareMessageData;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessage.ProposalMessageData;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessage.RoundChangeMessageData;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.Payload;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.ProposalPayload;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.SignedData;
+import tech.pegasys.pantheon.consensus.ibft.network.IbftNetworkPeers;
+import tech.pegasys.pantheon.consensus.ibft.network.MockPeerFactory;
+import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
+import tech.pegasys.pantheon.ethereum.core.Address;
+import tech.pegasys.pantheon.ethereum.core.AddressHelpers;
+import tech.pegasys.pantheon.ethereum.p2p.api.Message;
+import tech.pegasys.pantheon.ethereum.p2p.api.MessageData;
+import tech.pegasys.pantheon.ethereum.p2p.api.PeerConnection;
+import tech.pegasys.pantheon.ethereum.p2p.wire.DefaultMessage;
+
+import java.util.function.Function;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class IbftGossipTest {
+ private IbftGossip ibftGossip;
+ @Mock private IbftNetworkPeers ibftNetworkPeers;
+ private PeerConnection peerConnection;
+ private static final Address senderAddress = AddressHelpers.ofValue(9);
+
+ @Before
+ public void setup() {
+ ibftGossip = new IbftGossip(ibftNetworkPeers, 10);
+ peerConnection = MockPeerFactory.create(senderAddress);
+ }
+
+ private void assertRebroadcastToAllExceptSignerAndSender(
+ final Function> createPayload,
+ final Function, MessageData> createMessageData) {
+ final KeyPair keypair = KeyPair.generate();
+ final SignedData payload = createPayload.apply(keypair);
+ final MessageData messageData = createMessageData.apply(payload);
+ final Message message = new DefaultMessage(peerConnection, messageData);
+
+ final boolean gossipResult = ibftGossip.gossipMessage(message);
+ assertThat(gossipResult).isTrue();
+ verify(ibftNetworkPeers)
+ .multicastToValidatorsExcept(messageData, newArrayList(senderAddress, payload.getSender()));
+ }
+
+ private
void assertRebroadcastOnlyOnce(
+ final Function> createPayload,
+ final Function, MessageData> createMessageData) {
+ final KeyPair keypair = KeyPair.generate();
+ final SignedData payload = createPayload.apply(keypair);
+ final MessageData messageData = createMessageData.apply(payload);
+ final Message message = new DefaultMessage(peerConnection, messageData);
+
+ final boolean gossip1Result = ibftGossip.gossipMessage(message);
+ final boolean gossip2Result = ibftGossip.gossipMessage(message);
+ assertThat(gossip1Result).isTrue();
+ assertThat(gossip2Result).isFalse();
+ verify(ibftNetworkPeers, times(1))
+ .multicastToValidatorsExcept(messageData, newArrayList(senderAddress, payload.getSender()));
+ }
+
+ @Test
+ public void assertRebroadcastsProposalToAllExceptSignerAndSender() {
+ assertRebroadcastToAllExceptSignerAndSender(
+ TestHelpers::createSignedProposalPayload, ProposalMessageData::create);
+ }
+
+ @Test
+ public void assertRebroadcastsProposalOnlyOnce() {
+ assertRebroadcastOnlyOnce(
+ TestHelpers::createSignedProposalPayload, ProposalMessageData::create);
+ }
+
+ @Test
+ public void assertRebroadcastsPrepareToAllExceptSignerAndSender() {
+ assertRebroadcastToAllExceptSignerAndSender(
+ TestHelpers::createSignedPreparePayload, PrepareMessageData::create);
+ }
+
+ @Test
+ public void assertRebroadcastsPrepareOnlyOnce() {
+ assertRebroadcastOnlyOnce(TestHelpers::createSignedPreparePayload, PrepareMessageData::create);
+ }
+
+ @Test
+ public void assertRebroadcastsCommitToAllExceptSignerAndSender() {
+ assertRebroadcastToAllExceptSignerAndSender(
+ TestHelpers::createSignedCommitPayload, CommitMessageData::create);
+ }
+
+ @Test
+ public void assertRebroadcastsCommitOnlyOnce() {
+ assertRebroadcastOnlyOnce(TestHelpers::createSignedCommitPayload, CommitMessageData::create);
+ }
+
+ @Test
+ public void assertRebroadcastsRoundChangeToAllExceptSignerAndSender() {
+ assertRebroadcastToAllExceptSignerAndSender(
+ TestHelpers::createSignedRoundChangePayload, RoundChangeMessageData::create);
+ }
+
+ @Test
+ public void assertRebroadcastsRoundChangeOnlyOnce() {
+ assertRebroadcastOnlyOnce(
+ TestHelpers::createSignedRoundChangePayload, RoundChangeMessageData::create);
+ }
+
+ @Test
+ public void assertRebroadcastsNewRoundToAllExceptSignerAndSender() {
+ assertRebroadcastToAllExceptSignerAndSender(
+ TestHelpers::createSignedNewRoundPayload, NewRoundMessageData::create);
+ }
+
+ @Test
+ public void assertRebroadcastsNewRoundOnlyOnce() {
+ assertRebroadcastOnlyOnce(
+ TestHelpers::createSignedNewRoundPayload, NewRoundMessageData::create);
+ }
+
+ @Test
+ public void evictMessageRecordAtCapacity() {
+ final KeyPair keypair = KeyPair.generate();
+ final SignedData payload =
+ TestHelpers.createSignedProposalPayloadWithRound(keypair, 0);
+ final MessageData messageData = ProposalMessageData.create(payload);
+ final Message message = new DefaultMessage(peerConnection, messageData);
+ final boolean gossip1Result = ibftGossip.gossipMessage(message);
+ final boolean gossip2Result = ibftGossip.gossipMessage(message);
+ assertThat(gossip1Result).isTrue();
+ assertThat(gossip2Result).isFalse();
+ verify(ibftNetworkPeers, times(1))
+ .multicastToValidatorsExcept(messageData, newArrayList(senderAddress, payload.getSender()));
+
+ for (int i = 1; i <= 9; i++) {
+ final SignedData nextPayload =
+ TestHelpers.createSignedProposalPayloadWithRound(keypair, i);
+ final MessageData nextMessageData = ProposalMessageData.create(nextPayload);
+ final Message nextMessage = new DefaultMessage(peerConnection, nextMessageData);
+ final boolean nextGossipResult = ibftGossip.gossipMessage(nextMessage);
+ assertThat(nextGossipResult).isTrue();
+ }
+
+ final boolean gossip3Result = ibftGossip.gossipMessage(message);
+ assertThat(gossip3Result).isFalse();
+ verify(ibftNetworkPeers, times(1))
+ .multicastToValidatorsExcept(messageData, newArrayList(senderAddress, payload.getSender()));
+
+ {
+ final SignedData nextPayload =
+ TestHelpers.createSignedProposalPayloadWithRound(keypair, 10);
+ final MessageData nextMessageData = ProposalMessageData.create(nextPayload);
+ final Message nextMessage = new DefaultMessage(peerConnection, nextMessageData);
+ final boolean nextGossipResult = ibftGossip.gossipMessage(nextMessage);
+ assertThat(nextGossipResult).isTrue();
+ }
+
+ final boolean gossip4Result = ibftGossip.gossipMessage(message);
+ assertThat(gossip4Result).isTrue();
+ verify(ibftNetworkPeers, times(2))
+ .multicastToValidatorsExcept(messageData, newArrayList(senderAddress, payload.getSender()));
+
+ final boolean gossip5Result = ibftGossip.gossipMessage(message);
+ assertThat(gossip5Result).isFalse();
+ verify(ibftNetworkPeers, times(2))
+ .multicastToValidatorsExcept(messageData, newArrayList(senderAddress, payload.getSender()));
+ }
+}
diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/TestHelpers.java b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/TestHelpers.java
index fb208e7357..2104acec1d 100644
--- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/TestHelpers.java
+++ b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/TestHelpers.java
@@ -12,12 +12,28 @@
*/
package tech.pegasys.pantheon.consensus.ibft;
+import static com.google.common.collect.Lists.newArrayList;
+import static java.util.Collections.singletonList;
+
+import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.CommitPayload;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.MessageFactory;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.NewRoundPayload;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.PreparePayload;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.ProposalPayload;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.RoundChangeCertificate;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.RoundChangePayload;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.SignedData;
+import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
+import tech.pegasys.pantheon.crypto.SECP256K1.Signature;
import tech.pegasys.pantheon.ethereum.core.Address;
+import tech.pegasys.pantheon.ethereum.core.AddressHelpers;
import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.BlockDataGenerator;
import tech.pegasys.pantheon.ethereum.core.BlockDataGenerator.BlockOptions;
+import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.util.bytes.BytesValue;
+import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@@ -45,4 +61,53 @@ public class TestHelpers {
.setBlockHashFunction(IbftBlockHashing::calculateDataHashForCommittedSeal);
return new BlockDataGenerator().block(blockOptions);
}
+
+ public static SignedData createSignedProposalPayload(final KeyPair signerKeys) {
+ return createSignedProposalPayloadWithRound(signerKeys, 0xFEDCBA98);
+ }
+
+ public static SignedData createSignedProposalPayloadWithRound(
+ final KeyPair signerKeys, final int round) {
+ final MessageFactory messageFactory = new MessageFactory(signerKeys);
+ final ConsensusRoundIdentifier roundIdentifier =
+ new ConsensusRoundIdentifier(0x1234567890ABCDEFL, round);
+ final Block block =
+ TestHelpers.createProposalBlock(singletonList(AddressHelpers.ofValue(1)), 0);
+ return messageFactory.createSignedProposalPayload(roundIdentifier, block);
+ }
+
+ public static SignedData createSignedPreparePayload(final KeyPair signerKeys) {
+ final MessageFactory messageFactory = new MessageFactory(signerKeys);
+ final ConsensusRoundIdentifier roundIdentifier =
+ new ConsensusRoundIdentifier(0x1234567890ABCDEFL, 0xFEDCBA98);
+ return messageFactory.createSignedPreparePayload(
+ roundIdentifier, Hash.fromHexStringLenient("0"));
+ }
+
+ public static SignedData createSignedCommitPayload(final KeyPair signerKeys) {
+ final MessageFactory messageFactory = new MessageFactory(signerKeys);
+ final ConsensusRoundIdentifier roundIdentifier =
+ new ConsensusRoundIdentifier(0x1234567890ABCDEFL, 0xFEDCBA98);
+ return messageFactory.createSignedCommitPayload(
+ roundIdentifier,
+ Hash.fromHexStringLenient("0"),
+ Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 0));
+ }
+
+ public static SignedData createSignedRoundChangePayload(
+ final KeyPair signerKeys) {
+ final MessageFactory messageFactory = new MessageFactory(signerKeys);
+ final ConsensusRoundIdentifier roundIdentifier =
+ new ConsensusRoundIdentifier(0x1234567890ABCDEFL, 0xFEDCBA98);
+ return messageFactory.createSignedRoundChangePayload(roundIdentifier, Optional.empty());
+ }
+
+ public static SignedData createSignedNewRoundPayload(final KeyPair signerKeys) {
+ final MessageFactory messageFactory = new MessageFactory(signerKeys);
+ final ConsensusRoundIdentifier roundIdentifier =
+ new ConsensusRoundIdentifier(0x1234567890ABCDEFL, 0xFEDCBA98);
+ final SignedData proposalPayload = createSignedProposalPayload(signerKeys);
+ return messageFactory.createSignedNewRoundPayload(
+ roundIdentifier, new RoundChangeCertificate(newArrayList()), proposalPayload);
+ }
}
diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/CommitMessageTest.java b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/CommitMessageTest.java
index 01ef9a5bb6..7471b2d3d6 100644
--- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/CommitMessageTest.java
+++ b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/CommitMessageTest.java
@@ -32,12 +32,12 @@ public class CommitMessageTest {
@Mock private SignedData commitPayload;
@Mock private BytesValue messageBytes;
@Mock private MessageData messageData;
- @Mock private CommitMessage commitMessage;
+ @Mock private CommitMessageData commitMessage;
@Test
public void createMessageFromCommitMessageData() {
when(commitPayload.encode()).thenReturn(messageBytes);
- CommitMessage commitMessage = CommitMessage.create(commitPayload);
+ CommitMessageData commitMessage = CommitMessageData.create(commitPayload);
assertThat(commitMessage.getData()).isEqualTo(messageBytes);
assertThat(commitMessage.getCode()).isEqualTo(IbftV2.COMMIT);
@@ -46,7 +46,7 @@ public class CommitMessageTest {
@Test
public void createMessageFromCommitMessage() {
- CommitMessage message = CommitMessage.fromMessage(commitMessage);
+ CommitMessageData message = CommitMessageData.fromMessageData(commitMessage);
assertThat(message).isSameAs(commitMessage);
}
@@ -54,7 +54,7 @@ public class CommitMessageTest {
public void createMessageFromGenericMessageData() {
when(messageData.getData()).thenReturn(messageBytes);
when(messageData.getCode()).thenReturn(IbftV2.COMMIT);
- CommitMessage commitMessage = CommitMessage.fromMessage(messageData);
+ CommitMessageData commitMessage = CommitMessageData.fromMessageData(messageData);
assertThat(commitMessage.getData()).isEqualTo(messageData.getData());
assertThat(commitMessage.getCode()).isEqualTo(IbftV2.COMMIT);
@@ -63,8 +63,8 @@ public class CommitMessageTest {
@Test
public void createMessageFailsWhenIncorrectMessageCode() {
when(messageData.getCode()).thenReturn(42);
- assertThatThrownBy(() -> CommitMessage.fromMessage(messageData))
+ assertThatThrownBy(() -> CommitMessageData.fromMessageData(messageData))
.isInstanceOf(IllegalArgumentException.class)
- .hasMessageContaining("Message has code 42 and thus is not a CommitMessage");
+ .hasMessageContaining("MessageData has code 42 and thus is not a CommitMessageData");
}
}
diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/NewRoundMessageTest.java b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/NewRoundMessageTest.java
index e43cfc3b14..fe1511ff5e 100644
--- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/NewRoundMessageTest.java
+++ b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/NewRoundMessageTest.java
@@ -32,12 +32,12 @@ public class NewRoundMessageTest {
@Mock private SignedData newRoundPayload;
@Mock private BytesValue messageBytes;
@Mock private MessageData messageData;
- @Mock private NewRoundMessage newRoundMessage;
+ @Mock private NewRoundMessageData newRoundMessage;
@Test
public void createMessageFromNewRoundChangeMessageData() {
when(newRoundPayload.encode()).thenReturn(messageBytes);
- NewRoundMessage prepareMessage = NewRoundMessage.create(newRoundPayload);
+ NewRoundMessageData prepareMessage = NewRoundMessageData.create(newRoundPayload);
assertThat(prepareMessage.getData()).isEqualTo(messageBytes);
assertThat(prepareMessage.getCode()).isEqualTo(IbftV2.NEW_ROUND);
@@ -46,7 +46,7 @@ public class NewRoundMessageTest {
@Test
public void createMessageFromNewRoundMessage() {
- NewRoundMessage message = NewRoundMessage.fromMessage(newRoundMessage);
+ NewRoundMessageData message = NewRoundMessageData.fromMessageData(newRoundMessage);
assertThat(message).isSameAs(newRoundMessage);
}
@@ -54,7 +54,7 @@ public class NewRoundMessageTest {
public void createMessageFromGenericMessageData() {
when(messageData.getData()).thenReturn(messageBytes);
when(messageData.getCode()).thenReturn(IbftV2.NEW_ROUND);
- NewRoundMessage newRoundMessage = NewRoundMessage.fromMessage(messageData);
+ NewRoundMessageData newRoundMessage = NewRoundMessageData.fromMessageData(messageData);
assertThat(newRoundMessage.getData()).isEqualTo(messageData.getData());
assertThat(newRoundMessage.getCode()).isEqualTo(IbftV2.NEW_ROUND);
@@ -63,8 +63,8 @@ public class NewRoundMessageTest {
@Test
public void createMessageFailsWhenIncorrectMessageCode() {
when(messageData.getCode()).thenReturn(42);
- assertThatThrownBy(() -> NewRoundMessage.fromMessage(messageData))
+ assertThatThrownBy(() -> NewRoundMessageData.fromMessageData(messageData))
.isInstanceOf(IllegalArgumentException.class)
- .hasMessageContaining("Message has code 42 and thus is not a NewRoundMessage");
+ .hasMessageContaining("MessageData has code 42 and thus is not a NewRoundMessageData");
}
}
diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/PrepareMessageTest.java b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/PrepareMessageTest.java
index 5b30449977..363c19d14e 100644
--- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/PrepareMessageTest.java
+++ b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/PrepareMessageTest.java
@@ -32,12 +32,12 @@ public class PrepareMessageTest {
@Mock private SignedData preparePayload;
@Mock private BytesValue messageBytes;
@Mock private MessageData messageData;
- @Mock private PrepareMessage prepareMessage;
+ @Mock private PrepareMessageData prepareMessage;
@Test
public void createMessageFromPrepareMessageData() {
when(preparePayload.encode()).thenReturn(messageBytes);
- PrepareMessage prepareMessage = PrepareMessage.create(preparePayload);
+ PrepareMessageData prepareMessage = PrepareMessageData.create(preparePayload);
assertThat(prepareMessage.getData()).isEqualTo(messageBytes);
assertThat(prepareMessage.getCode()).isEqualTo(IbftV2.PREPARE);
@@ -46,7 +46,7 @@ public class PrepareMessageTest {
@Test
public void createMessageFromPrepareMessage() {
- PrepareMessage message = PrepareMessage.fromMessage(prepareMessage);
+ PrepareMessageData message = PrepareMessageData.fromMessageData(prepareMessage);
assertThat(message).isSameAs(prepareMessage);
}
@@ -54,7 +54,7 @@ public class PrepareMessageTest {
public void createMessageFromGenericMessageData() {
when(messageData.getData()).thenReturn(messageBytes);
when(messageData.getCode()).thenReturn(IbftV2.PREPARE);
- PrepareMessage prepareMessage = PrepareMessage.fromMessage(messageData);
+ PrepareMessageData prepareMessage = PrepareMessageData.fromMessageData(messageData);
assertThat(prepareMessage.getData()).isEqualTo(messageData.getData());
assertThat(prepareMessage.getCode()).isEqualTo(IbftV2.PREPARE);
@@ -63,8 +63,8 @@ public class PrepareMessageTest {
@Test
public void createMessageFailsWhenIncorrectMessageCode() {
when(messageData.getCode()).thenReturn(42);
- assertThatThrownBy(() -> PrepareMessage.fromMessage(messageData))
+ assertThatThrownBy(() -> PrepareMessageData.fromMessageData(messageData))
.isInstanceOf(IllegalArgumentException.class)
- .hasMessageContaining("Message has code 42 and thus is not a PrepareMessage");
+ .hasMessageContaining("MessageData has code 42 and thus is not a PrepareMessageData");
}
}
diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/PrePrepareMessageTest.java b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/ProposalMessageTest.java
similarity index 75%
rename from consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/PrePrepareMessageTest.java
rename to consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/ProposalMessageTest.java
index 44fdecf769..9480e2bfe7 100644
--- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/PrePrepareMessageTest.java
+++ b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/ProposalMessageTest.java
@@ -28,25 +28,25 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
-public class PrePrepareMessageTest {
- @Mock private SignedData prePrepareMessageData;
+public class ProposalMessageTest {
+ @Mock private SignedData proposalMessageData;
@Mock private BytesValue messageBytes;
@Mock private MessageData messageData;
- @Mock private ProposalMessage proposalMessage;
+ @Mock private ProposalMessageData proposalMessage;
@Test
public void createMessageFromPrePrepareMessageData() {
- when(prePrepareMessageData.encode()).thenReturn(messageBytes);
- ProposalMessage proposalMessage = ProposalMessage.create(prePrepareMessageData);
+ when(proposalMessageData.encode()).thenReturn(messageBytes);
+ final ProposalMessageData proposalMessage = ProposalMessageData.create(proposalMessageData);
assertThat(proposalMessage.getData()).isEqualTo(messageBytes);
assertThat(proposalMessage.getCode()).isEqualTo(IbftV2.PROPOSAL);
- verify(prePrepareMessageData).encode();
+ verify(proposalMessageData).encode();
}
@Test
public void createMessageFromPrePrepareMessage() {
- ProposalMessage message = ProposalMessage.fromMessage(proposalMessage);
+ final ProposalMessageData message = ProposalMessageData.fromMessageData(proposalMessage);
assertThat(message).isSameAs(proposalMessage);
}
@@ -54,7 +54,7 @@ public class PrePrepareMessageTest {
public void createMessageFromGenericMessageData() {
when(messageData.getCode()).thenReturn(IbftV2.PROPOSAL);
when(messageData.getData()).thenReturn(messageBytes);
- ProposalMessage proposalMessage = ProposalMessage.fromMessage(messageData);
+ final ProposalMessageData proposalMessage = ProposalMessageData.fromMessageData(messageData);
assertThat(proposalMessage.getData()).isEqualTo(messageData.getData());
assertThat(proposalMessage.getCode()).isEqualTo(IbftV2.PROPOSAL);
@@ -63,8 +63,8 @@ public class PrePrepareMessageTest {
@Test
public void createMessageFailsWhenIncorrectMessageCode() {
when(messageData.getCode()).thenReturn(42);
- assertThatThrownBy(() -> ProposalMessage.fromMessage(messageData))
+ assertThatThrownBy(() -> ProposalMessageData.fromMessageData(messageData))
.isInstanceOf(IllegalArgumentException.class)
- .hasMessageContaining("Message has code 42 and thus is not a ProposalMessage");
+ .hasMessageContaining("MessageData has code 42 and thus is not a ProposalMessageData");
}
}
diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/RoundChangeMessageTest.java b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/RoundChangeMessageTest.java
index 71bfd6fbcb..59686579bb 100644
--- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/RoundChangeMessageTest.java
+++ b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/ibftmessage/RoundChangeMessageTest.java
@@ -32,12 +32,12 @@ public class RoundChangeMessageTest {
@Mock private SignedData roundChangePayload;
@Mock private BytesValue messageBytes;
@Mock private MessageData messageData;
- @Mock private RoundChangeMessage roundChangeMessage;
+ @Mock private RoundChangeMessageData roundChangeMessage;
@Test
public void createMessageFromRoundChangeMessageData() {
when(roundChangePayload.encode()).thenReturn(messageBytes);
- RoundChangeMessage roundChangeMessage = RoundChangeMessage.create(roundChangePayload);
+ RoundChangeMessageData roundChangeMessage = RoundChangeMessageData.create(roundChangePayload);
assertThat(roundChangeMessage.getData()).isEqualTo(messageBytes);
assertThat(roundChangeMessage.getCode()).isEqualTo(IbftV2.ROUND_CHANGE);
@@ -46,7 +46,7 @@ public class RoundChangeMessageTest {
@Test
public void createMessageFromRoundChangeMessage() {
- RoundChangeMessage message = RoundChangeMessage.fromMessage(roundChangeMessage);
+ RoundChangeMessageData message = RoundChangeMessageData.fromMessageData(roundChangeMessage);
assertThat(message).isSameAs(roundChangeMessage);
}
@@ -54,7 +54,7 @@ public class RoundChangeMessageTest {
public void createMessageFromGenericMessageData() {
when(messageData.getData()).thenReturn(messageBytes);
when(messageData.getCode()).thenReturn(IbftV2.ROUND_CHANGE);
- RoundChangeMessage roundChangeMessage = RoundChangeMessage.fromMessage(messageData);
+ RoundChangeMessageData roundChangeMessage = RoundChangeMessageData.fromMessageData(messageData);
assertThat(roundChangeMessage.getData()).isEqualTo(messageData.getData());
assertThat(roundChangeMessage.getCode()).isEqualTo(IbftV2.ROUND_CHANGE);
@@ -63,8 +63,8 @@ public class RoundChangeMessageTest {
@Test
public void createMessageFailsWhenIncorrectMessageCode() {
when(messageData.getCode()).thenReturn(42);
- assertThatThrownBy(() -> RoundChangeMessage.fromMessage(messageData))
+ assertThatThrownBy(() -> RoundChangeMessageData.fromMessageData(messageData))
.isInstanceOf(IllegalArgumentException.class)
- .hasMessageContaining("Message has code 42 and thus is not a RoundChangeMessage");
+ .hasMessageContaining("MessageData has code 42 and thus is not a RoundChangeMessageData");
}
}
diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/network/IbftNetworkPeersTest.java b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/network/IbftNetworkPeersTest.java
index 3609bdc829..f077ef790a 100644
--- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/network/IbftNetworkPeersTest.java
+++ b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/network/IbftNetworkPeersTest.java
@@ -12,6 +12,7 @@
*/
package tech.pegasys.pantheon.consensus.ibft.network;
+import static com.google.common.collect.Lists.newArrayList;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -33,7 +34,6 @@ import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.math.BigInteger;
import java.util.List;
-import com.google.common.collect.Lists;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -42,21 +42,22 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class IbftNetworkPeersTest {
- private final List validators = Lists.newArrayList();
- private final List publicKeys = Lists.newArrayList();
+ private final List validators = newArrayList();
+ private final List publicKeys = newArrayList();
- private final List peerConnections = Lists.newArrayList();
+ private final List peerConnections = newArrayList();
@Before
public void setup() {
for (int i = 0; i < 4; i++) {
final PublicKey pubKey = PublicKey.create(BigInteger.valueOf(i));
publicKeys.add(pubKey);
+ final Address address = Util.publicKeyToAddress(pubKey);
final PeerInfo peerInfo = mock(PeerInfo.class);
final PeerConnection peerConnection = mock(PeerConnection.class);
when(peerConnection.getPeer()).thenReturn(peerInfo);
- when(peerInfo.getNodeId()).thenReturn(pubKey.getEncodedBytes());
+ when(peerInfo.getAddress()).thenReturn(address);
peerConnections.add(peerConnection);
}
@@ -93,7 +94,7 @@ public class IbftNetworkPeersTest {
final IbftNetworkPeers peers = new IbftNetworkPeers(validatorProvider);
// only add peer connections 1, 2 & 3, none of which should be invoked.
- Lists.newArrayList(1, 2, 3).forEach(i -> peers.peerAdded(peerConnections.get(i)));
+ newArrayList(1, 2, 3).forEach(i -> peers.peerAdded(peerConnections.get(i)));
final MessageData messageToSend = new RawMessage(1, BytesValue.EMPTY);
peers.multicastToValidators(messageToSend);
@@ -103,4 +104,27 @@ public class IbftNetworkPeersTest {
verify(peerConnections.get(2), never()).sendForProtocol(any(), any());
verify(peerConnections.get(3), never()).sendForProtocol(any(), any());
}
+
+ @Test
+ public void onlyValidatorsAreSentAMessageNotInExcludes() throws PeerNotConnected {
+ // Only add the first Peer's address to the validators.
+ final Address validatorAddress = Util.publicKeyToAddress(publicKeys.get(0));
+ validators.add(validatorAddress);
+ validators.add(Util.publicKeyToAddress(publicKeys.get(1)));
+ final ValidatorProvider validatorProvider = mock(ValidatorProvider.class);
+ when(validatorProvider.getValidators()).thenReturn(validators);
+
+ final IbftNetworkPeers peers = new IbftNetworkPeers(validatorProvider);
+ for (final PeerConnection peer : peerConnections) {
+ peers.peerAdded(peer);
+ }
+
+ final MessageData messageToSend = new RawMessage(1, BytesValue.EMPTY);
+ peers.multicastToValidatorsExcept(messageToSend, newArrayList(validatorAddress));
+
+ verify(peerConnections.get(0), never()).sendForProtocol(any(), any());
+ verify(peerConnections.get(1), times(1)).sendForProtocol(any(), any());
+ verify(peerConnections.get(2), never()).sendForProtocol(any(), any());
+ verify(peerConnections.get(3), never()).sendForProtocol(any(), any());
+ }
}
diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/network/MockPeerFactory.java b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/network/MockPeerFactory.java
new file mode 100644
index 0000000000..150e47b5a1
--- /dev/null
+++ b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/network/MockPeerFactory.java
@@ -0,0 +1,40 @@
+/*
+ * 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.network;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import tech.pegasys.pantheon.ethereum.core.Address;
+import tech.pegasys.pantheon.ethereum.core.AddressHelpers;
+import tech.pegasys.pantheon.ethereum.p2p.api.PeerConnection;
+import tech.pegasys.pantheon.ethereum.p2p.wire.PeerInfo;
+
+public class MockPeerFactory {
+ public static PeerConnection create() {
+ return create(AddressHelpers.ofValue(9));
+ }
+
+ public static PeerConnection create(final Address address) {
+ final PeerConnection peerConnection = mock(PeerConnection.class);
+ final PeerInfo peerInfo = createPeerInfo(address);
+ when(peerConnection.getPeer()).thenReturn(peerInfo);
+ return peerConnection;
+ }
+
+ public static PeerInfo createPeerInfo(final Address address) {
+ final PeerInfo peerInfo = mock(PeerInfo.class);
+ when(peerInfo.getAddress()).thenReturn(address);
+ return peerInfo;
+ }
+}
diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java
index 2475399490..713b2a38d9 100644
--- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java
+++ b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java
@@ -233,7 +233,7 @@ public class IbftBlockHeightManagerTest {
manager.start();
verify(roundFactory).createNewRound(any(), eq(0));
- manager.handleRoundChangeMessage(roundChangePayload);
+ manager.handleRoundChangePayload(roundChangePayload);
verify(roundChangeManager, times(1)).appendRoundChangeMessage(roundChangePayload);
verify(roundFactory, times(1))
@@ -279,7 +279,7 @@ public class IbftBlockHeightManagerTest {
messageValidatorFactory);
manager.start();
- manager.handleRoundChangeMessage(roundChangePayload);
+ manager.handleRoundChangePayload(roundChangePayload);
verify(messageTransmitter, times(1))
.multicastNewRound(eq(futureRoundIdentifier), eq(roundChangCert), any());
@@ -311,8 +311,8 @@ public class IbftBlockHeightManagerTest {
Hash.fromHexStringLenient("0"),
Signature.create(BigInteger.ONE, BigInteger.ONE, (byte) 1));
- manager.handlePrepareMessage(preparePayload);
- manager.handleCommitMessage(commitPayload);
+ manager.handlePreparePayload(preparePayload);
+ manager.handleCommitPayload(commitPayload);
// Force a new round to be started at new round number.
final SignedData newRound =
@@ -321,7 +321,7 @@ public class IbftBlockHeightManagerTest {
new RoundChangeCertificate(Collections.emptyList()),
messageFactory.createSignedProposalPayload(futureRoundIdentifier, createdBlock));
- manager.handleNewRoundMessage(newRound);
+ manager.handleNewRoundPayload(newRound);
// Final state sets the Quorum Size to 3, so should send a Prepare and also a commit
verify(messageTransmitter, times(1)).multicastPrepare(eq(futureRoundIdentifier), any());
@@ -349,8 +349,8 @@ public class IbftBlockHeightManagerTest {
validatorMessageFactory
.get(1)
.createSignedPreparePayload(roundIdentifier, Hash.fromHexStringLenient("0"));
- manager.handlePrepareMessage(preparePayload);
- manager.handlePrepareMessage(secondPreparePayload);
+ manager.handlePreparePayload(preparePayload);
+ manager.handlePreparePayload(secondPreparePayload);
manager.roundExpired(new RoundExpiry(roundIdentifier));
diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftControllerTest.java b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftControllerTest.java
index 2ebe78f0cd..85ecdd4b08 100644
--- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftControllerTest.java
+++ b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftControllerTest.java
@@ -12,7 +12,7 @@
*/
package tech.pegasys.pantheon.consensus.ibft.statemachine;
-import static org.assertj.core.api.Java6Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.util.Lists.newArrayList;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.atLeastOnce;
@@ -22,16 +22,17 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
+import tech.pegasys.pantheon.consensus.ibft.IbftGossip;
import tech.pegasys.pantheon.consensus.ibft.ibftevent.BlockTimerExpiry;
import tech.pegasys.pantheon.consensus.ibft.ibftevent.IbftReceivedMessageEvent;
import tech.pegasys.pantheon.consensus.ibft.ibftevent.NewChainHead;
import tech.pegasys.pantheon.consensus.ibft.ibftevent.RoundExpiry;
-import tech.pegasys.pantheon.consensus.ibft.ibftmessage.CommitMessage;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessage.CommitMessageData;
import tech.pegasys.pantheon.consensus.ibft.ibftmessage.IbftV2;
-import tech.pegasys.pantheon.consensus.ibft.ibftmessage.NewRoundMessage;
-import tech.pegasys.pantheon.consensus.ibft.ibftmessage.PrepareMessage;
-import tech.pegasys.pantheon.consensus.ibft.ibftmessage.ProposalMessage;
-import tech.pegasys.pantheon.consensus.ibft.ibftmessage.RoundChangeMessage;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessage.NewRoundMessageData;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessage.PrepareMessageData;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessage.ProposalMessageData;
+import tech.pegasys.pantheon.consensus.ibft.ibftmessage.RoundChangeMessageData;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.CommitPayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.NewRoundPayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.PreparePayload;
@@ -41,7 +42,8 @@ import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.SignedData;
import tech.pegasys.pantheon.ethereum.chain.Blockchain;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
-import tech.pegasys.pantheon.ethereum.p2p.api.MessageData;
+import tech.pegasys.pantheon.ethereum.p2p.api.Message;
+import tech.pegasys.pantheon.ethereum.p2p.wire.DefaultMessage;
import java.util.HashMap;
import java.util.List;
@@ -64,39 +66,46 @@ public class IbftControllerTest {
@Mock private IbftBlockHeightManager blockHeightManager;
@Mock private SignedData signedProposal;
- @Mock private ProposalMessage proposalMessage;
+ private Message proposalMessage;
+ @Mock private ProposalMessageData proposalMessageData;
@Mock private ProposalPayload proposalPayload;
@Mock private SignedData signedPrepare;
- @Mock private PrepareMessage prepareMessage;
+ private Message prepareMessage;
+ @Mock private PrepareMessageData prepareMessageData;
@Mock private PreparePayload preparePayload;
@Mock private SignedData signedCommit;
- @Mock private CommitMessage commitMessage;
+ private Message commitMessage;
+ @Mock private CommitMessageData commitMessageData;
@Mock private CommitPayload commitPayload;
@Mock private SignedData signedNewRound;
- @Mock private NewRoundMessage newRoundMessage;
+ private Message newRoundMessage;
+ @Mock private NewRoundMessageData newRoundMessageData;
@Mock private NewRoundPayload newRoundPayload;
@Mock private SignedData signedRoundChange;
- @Mock private RoundChangeMessage roundChangeMessage;
+ private Message roundChangeMessage;
+ @Mock private RoundChangeMessageData roundChangeMessageData;
@Mock private RoundChangePayload roundChangePayload;
- private final Map> futureMessages = new HashMap<>();
+ private final Map> futureMessages = new HashMap<>();
private final Address validator = Address.fromHexString("0x0");
private final Address unknownValidator = Address.fromHexString("0x2");
private final ConsensusRoundIdentifier futureRoundIdentifier = new ConsensusRoundIdentifier(2, 0);
private ConsensusRoundIdentifier roundIdentifier = new ConsensusRoundIdentifier(0, 0);
+ @Mock private IbftGossip ibftGossip;
private IbftController ibftController;
@Before
public void setup() {
- ibftController =
- new IbftController(blockChain, ibftFinalState, blockHeightManagerFactory, futureMessages);
when(blockChain.getChainHeadHeader()).thenReturn(blockHeader);
when(blockHeightManagerFactory.create(blockHeader)).thenReturn(blockHeightManager);
when(ibftFinalState.getValidators()).thenReturn(ImmutableList.of(validator));
+ ibftController =
+ new IbftController(
+ blockChain, ibftFinalState, blockHeightManagerFactory, futureMessages, ibftGossip);
}
@Test
@@ -115,9 +124,9 @@ public class IbftControllerTest {
setupRoundChange(futureRoundIdentifier, validator);
setupNewRound(roundIdentifierHeight3, validator);
- final List height2Msgs =
+ final List height2Msgs =
newArrayList(prepareMessage, commitMessage, roundChangeMessage);
- final List height3Msgs = newArrayList(proposalMessage, newRoundMessage);
+ final List height3Msgs = newArrayList(proposalMessage, newRoundMessage);
futureMessages.put(2L, height2Msgs);
futureMessages.put(3L, height3Msgs);
when(blockHeightManager.getChainHeight()).thenReturn(2L);
@@ -128,11 +137,14 @@ public class IbftControllerTest {
verify(blockHeightManagerFactory).create(blockHeader);
verify(blockHeightManager, atLeastOnce()).getChainHeight();
verify(blockHeightManager).start();
- verify(blockHeightManager, never()).handleProposalMessage(signedProposal);
- verify(blockHeightManager).handlePrepareMessage(signedPrepare);
- verify(blockHeightManager).handleCommitMessage(signedCommit);
- verify(blockHeightManager).handleRoundChangeMessage(signedRoundChange);
- verify(blockHeightManager, never()).handleNewRoundMessage(signedNewRound);
+ verify(blockHeightManager, never()).handleProposalPayload(signedProposal);
+ verify(blockHeightManager).handlePreparePayload(signedPrepare);
+ verify(ibftGossip).gossipMessage(prepareMessage);
+ verify(blockHeightManager).handleCommitPayload(signedCommit);
+ verify(ibftGossip).gossipMessage(commitMessage);
+ verify(blockHeightManager).handleRoundChangePayload(signedRoundChange);
+ verify(ibftGossip).gossipMessage(roundChangeMessage);
+ verify(blockHeightManager, never()).handleNewRoundPayload(signedNewRound);
}
@Test
@@ -155,11 +167,16 @@ public class IbftControllerTest {
verify(blockHeightManagerFactory).create(blockHeader);
verify(blockHeightManager, atLeastOnce()).getChainHeight();
verify(blockHeightManager).start();
- verify(blockHeightManager).handleProposalMessage(signedProposal);
- verify(blockHeightManager).handlePrepareMessage(signedPrepare);
- verify(blockHeightManager).handleCommitMessage(signedCommit);
- verify(blockHeightManager).handleRoundChangeMessage(signedRoundChange);
- verify(blockHeightManager).handleNewRoundMessage(signedNewRound);
+ verify(blockHeightManager).handleProposalPayload(signedProposal);
+ verify(ibftGossip).gossipMessage(proposalMessage);
+ verify(blockHeightManager).handlePreparePayload(signedPrepare);
+ verify(ibftGossip).gossipMessage(prepareMessage);
+ verify(blockHeightManager).handleCommitPayload(signedCommit);
+ verify(ibftGossip).gossipMessage(commitMessage);
+ verify(blockHeightManager).handleRoundChangePayload(signedRoundChange);
+ verify(ibftGossip).gossipMessage(roundChangeMessage);
+ verify(blockHeightManager).handleNewRoundPayload(signedNewRound);
+ verify(ibftGossip).gossipMessage(newRoundMessage);
}
@Test
@@ -189,7 +206,8 @@ public class IbftControllerTest {
ibftController.handleMessageEvent(new IbftReceivedMessageEvent(proposalMessage));
assertThat(futureMessages).isEmpty();
- verify(blockHeightManager).handleProposalMessage(signedProposal);
+ verify(blockHeightManager).handleProposalPayload(signedProposal);
+ verify(ibftGossip).gossipMessage(proposalMessage);
verify(blockHeightManager, atLeastOnce()).getChainHeight();
verify(blockHeightManager).start();
verifyNoMoreInteractions(blockHeightManager);
@@ -202,7 +220,8 @@ public class IbftControllerTest {
ibftController.handleMessageEvent(new IbftReceivedMessageEvent(prepareMessage));
assertThat(futureMessages).isEmpty();
- verify(blockHeightManager).handlePrepareMessage(signedPrepare);
+ verify(blockHeightManager).handlePreparePayload(signedPrepare);
+ verify(ibftGossip).gossipMessage(prepareMessage);
verify(blockHeightManager, atLeastOnce()).getChainHeight();
verify(blockHeightManager).start();
verifyNoMoreInteractions(blockHeightManager);
@@ -215,7 +234,8 @@ public class IbftControllerTest {
ibftController.handleMessageEvent(new IbftReceivedMessageEvent(commitMessage));
assertThat(futureMessages).isEmpty();
- verify(blockHeightManager).handleCommitMessage(signedCommit);
+ verify(blockHeightManager).handleCommitPayload(signedCommit);
+ verify(ibftGossip).gossipMessage(commitMessage);
verify(blockHeightManager, atLeastOnce()).getChainHeight();
verify(blockHeightManager).start();
verifyNoMoreInteractions(blockHeightManager);
@@ -229,7 +249,8 @@ public class IbftControllerTest {
ibftController.handleMessageEvent(new IbftReceivedMessageEvent(newRoundMessage));
assertThat(futureMessages).isEmpty();
- verify(blockHeightManager).handleNewRoundMessage(signedNewRound);
+ verify(blockHeightManager).handleNewRoundPayload(signedNewRound);
+ verify(ibftGossip).gossipMessage(newRoundMessage);
verify(blockHeightManager, atLeastOnce()).getChainHeight();
verify(blockHeightManager).start();
verifyNoMoreInteractions(blockHeightManager);
@@ -243,7 +264,8 @@ public class IbftControllerTest {
ibftController.handleMessageEvent(new IbftReceivedMessageEvent(roundChangeMessage));
assertThat(futureMessages).isEmpty();
- verify(blockHeightManager).handleRoundChangeMessage(signedRoundChange);
+ verify(blockHeightManager).handleRoundChangePayload(signedRoundChange);
+ verify(ibftGossip).gossipMessage(roundChangeMessage);
verify(blockHeightManager, atLeastOnce()).getChainHeight();
verify(blockHeightManager).start();
verifyNoMoreInteractions(blockHeightManager);
@@ -337,7 +359,7 @@ public class IbftControllerTest {
@Test
public void proposalForFutureHeightIsBuffered() {
setupProposal(futureRoundIdentifier, validator);
- final Map> expectedFutureMsgs =
+ final Map> expectedFutureMsgs =
ImmutableMap.of(2L, ImmutableList.of(proposalMessage));
verifyHasFutureMessages(new IbftReceivedMessageEvent(proposalMessage), expectedFutureMsgs);
}
@@ -345,7 +367,7 @@ public class IbftControllerTest {
@Test
public void prepareForFutureHeightIsBuffered() {
setupPrepare(futureRoundIdentifier, validator);
- final Map> expectedFutureMsgs =
+ final Map> expectedFutureMsgs =
ImmutableMap.of(2L, ImmutableList.of(prepareMessage));
verifyHasFutureMessages(new IbftReceivedMessageEvent(prepareMessage), expectedFutureMsgs);
}
@@ -353,7 +375,7 @@ public class IbftControllerTest {
@Test
public void commitForFutureHeightIsBuffered() {
setupCommit(futureRoundIdentifier, validator);
- final Map> expectedFutureMsgs =
+ final Map> expectedFutureMsgs =
ImmutableMap.of(2L, ImmutableList.of(commitMessage));
verifyHasFutureMessages(new IbftReceivedMessageEvent(commitMessage), expectedFutureMsgs);
}
@@ -361,7 +383,7 @@ public class IbftControllerTest {
@Test
public void newRoundForFutureHeightIsBuffered() {
setupNewRound(futureRoundIdentifier, validator);
- final Map> expectedFutureMsgs =
+ final Map> expectedFutureMsgs =
ImmutableMap.of(2L, ImmutableList.of(newRoundMessage));
verifyHasFutureMessages(new IbftReceivedMessageEvent(newRoundMessage), expectedFutureMsgs);
}
@@ -369,7 +391,7 @@ public class IbftControllerTest {
@Test
public void roundChangeForFutureHeightIsBuffered() {
setupRoundChange(futureRoundIdentifier, validator);
- final Map> expectedFutureMsgs =
+ final Map> expectedFutureMsgs =
ImmutableMap.of(2L, ImmutableList.of(roundChangeMessage));
verifyHasFutureMessages(new IbftReceivedMessageEvent(roundChangeMessage), expectedFutureMsgs);
}
@@ -385,7 +407,7 @@ public class IbftControllerTest {
}
private void verifyHasFutureMessages(
- final IbftReceivedMessageEvent msg, final Map> expectedFutureMsgs) {
+ final IbftReceivedMessageEvent msg, final Map> expectedFutureMsgs) {
ibftController.start();
ibftController.handleMessageEvent(msg);
@@ -401,8 +423,9 @@ public class IbftControllerTest {
when(signedProposal.getPayload()).thenReturn(proposalPayload);
when(signedProposal.getSender()).thenReturn(validator);
when(proposalPayload.getRoundIdentifier()).thenReturn(roundIdentifier);
- when(proposalMessage.getCode()).thenReturn(IbftV2.PROPOSAL);
- when(proposalMessage.decode()).thenReturn(signedProposal);
+ when(proposalMessageData.getCode()).thenReturn(IbftV2.PROPOSAL);
+ when(proposalMessageData.decode()).thenReturn(signedProposal);
+ proposalMessage = new DefaultMessage(null, proposalMessageData);
}
private void setupPrepare(
@@ -410,8 +433,9 @@ public class IbftControllerTest {
when(signedPrepare.getPayload()).thenReturn(preparePayload);
when(signedPrepare.getSender()).thenReturn(validator);
when(preparePayload.getRoundIdentifier()).thenReturn(roundIdentifier);
- when(prepareMessage.getCode()).thenReturn(IbftV2.PREPARE);
- when(prepareMessage.decode()).thenReturn(signedPrepare);
+ when(prepareMessageData.getCode()).thenReturn(IbftV2.PREPARE);
+ when(prepareMessageData.decode()).thenReturn(signedPrepare);
+ prepareMessage = new DefaultMessage(null, prepareMessageData);
}
private void setupCommit(
@@ -419,8 +443,9 @@ public class IbftControllerTest {
when(signedCommit.getPayload()).thenReturn(commitPayload);
when(signedCommit.getSender()).thenReturn(validator);
when(commitPayload.getRoundIdentifier()).thenReturn(roundIdentifier);
- when(commitMessage.getCode()).thenReturn(IbftV2.COMMIT);
- when(commitMessage.decode()).thenReturn(signedCommit);
+ when(commitMessageData.getCode()).thenReturn(IbftV2.COMMIT);
+ when(commitMessageData.decode()).thenReturn(signedCommit);
+ commitMessage = new DefaultMessage(null, commitMessageData);
}
private void setupNewRound(
@@ -428,8 +453,9 @@ public class IbftControllerTest {
when(signedNewRound.getPayload()).thenReturn(newRoundPayload);
when(signedNewRound.getSender()).thenReturn(validator);
when(newRoundPayload.getRoundIdentifier()).thenReturn(roundIdentifier);
- when(newRoundMessage.getCode()).thenReturn(IbftV2.NEW_ROUND);
- when(newRoundMessage.decode()).thenReturn(signedNewRound);
+ when(newRoundMessageData.getCode()).thenReturn(IbftV2.NEW_ROUND);
+ when(newRoundMessageData.decode()).thenReturn(signedNewRound);
+ newRoundMessage = new DefaultMessage(null, newRoundMessageData);
}
private void setupRoundChange(
@@ -437,7 +463,8 @@ public class IbftControllerTest {
when(signedRoundChange.getPayload()).thenReturn(roundChangePayload);
when(signedRoundChange.getSender()).thenReturn(validator);
when(roundChangePayload.getRoundIdentifier()).thenReturn(roundIdentifier);
- when(roundChangeMessage.getCode()).thenReturn(IbftV2.ROUND_CHANGE);
- when(roundChangeMessage.decode()).thenReturn(signedRoundChange);
+ when(roundChangeMessageData.getCode()).thenReturn(IbftV2.ROUND_CHANGE);
+ when(roundChangeMessageData.decode()).thenReturn(signedRoundChange);
+ roundChangeMessage = new DefaultMessage(null, roundChangeMessageData);
}
}
diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/wire/AbstractMessageData.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/wire/AbstractMessageData.java
index 80da64bced..0ff7a35994 100644
--- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/wire/AbstractMessageData.java
+++ b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/wire/AbstractMessageData.java
@@ -15,6 +15,8 @@ package tech.pegasys.pantheon.ethereum.p2p.wire;
import tech.pegasys.pantheon.ethereum.p2p.api.MessageData;
import tech.pegasys.pantheon.util.bytes.BytesValue;
+import com.google.common.base.Objects;
+
public abstract class AbstractMessageData implements MessageData {
protected final BytesValue data;
@@ -32,4 +34,21 @@ public abstract class AbstractMessageData implements MessageData {
public BytesValue getData() {
return data;
}
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ final AbstractMessageData that = (AbstractMessageData) o;
+ return Objects.equal(data, that.data);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(data);
+ }
}
diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/wire/PeerInfo.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/wire/PeerInfo.java
index 0fbaac1802..f7bd0daf56 100644
--- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/wire/PeerInfo.java
+++ b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/wire/PeerInfo.java
@@ -14,6 +14,9 @@ package tech.pegasys.pantheon.ethereum.p2p.wire;
import static tech.pegasys.pantheon.util.bytes.BytesValue.wrap;
+import tech.pegasys.pantheon.crypto.SECP256K1.PublicKey;
+import tech.pegasys.pantheon.ethereum.core.Address;
+import tech.pegasys.pantheon.ethereum.core.Util;
import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
import tech.pegasys.pantheon.util.bytes.BytesValue;
@@ -82,6 +85,11 @@ public class PeerInfo {
return nodeId;
}
+ public Address getAddress() {
+ final PublicKey remotePublicKey = PublicKey.create(nodeId);
+ return Util.publicKeyToAddress(remotePublicKey);
+ }
+
public void writeTo(final RLPOutput out) {
out.startList();
out.writeUnsignedByte(getVersion());