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

[NC-1909] IBFT message gossiping #501

Merged
merged 38 commits into from
Jan 9, 2019

Conversation

Errorific
Copy link
Contributor

PR description

Need to retransmit IBFT messages that we receive. Need to not send them back to who we received them from and not to who originally signed them

* @return Boolean of whether the message was rebroadcast or ignored as it's already been
* broadcast in recent memory
*/
public boolean gossipPreparePayload(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'msg specific' functions could be removed, and the IbftController invoke gossipMessage directly. The "excludeAddress" would be the signer in that instance, rather than the sender.
I don't THINK there's a need to re-serialise the SignedData<?> into a messageData.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sender is available from the message object, the signer is available from the SignedData object, the signature I need to cache is in the SignedData object, dispatching a message requires it to be a MessageData. So at the end of everything all 3 (Message, MessageData, SignedData) need to be utilised at one level or another.

I've tried writing it a few ways and I've gotten to this version because it means the IbftController only needs to worry about the transport layer addresses when excluding things and the gossiper worries about the message contents. The other versions I've written didn't end up with a clean division of responsibilities.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know its not ideal - but in IbftController, can we not write:
gossiper.gossipMessage(payload.getSignature(),
messageData,
payload.getSender(),
payload.getSender(), message.getConnection().getPeer().getAddress());

Inside the handleMessage()? Or something similar in the new processMessage function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that's an improvement. This moves the concern for identifying a message from the gossiper to the controller. Ideally I'd like to pass a Message into the gossiper but with the type information that's lost about it's contents and the requirements to re decode the message I compromised and picked the most descriptive object that contained as much of the information I required as it could.

Copy link
Contributor

@rain-on rain-on Jan 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even better:

  public boolean gossipMessage(
      final SignedData<?> signedMessage,
      final Message message)  {
    final Signature msgUniqueId = signedMessage.getSignature();
    if (seenMessages.contains(msgUniqueId)) {
      return false;
    } else {
      final Address receivedFrom = message.getConnection().getPeer().getAddress();
      final List<Address> excludeAddressesList =
          Lists.newArrayList(receivedFrom, signedMessage.getSender());
      peers.multicastToValidatorsExcept(message.getData(), excludeAddressesList);
      seenMessages.add(msgUniqueId);
      return true;
    }
  }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't make encapsulation any better, the invoker needs to co-ordinate that the message contains that SignedData.

final BiConsumer<SignedData<P>, Address> gossipMessage,
final Consumer<SignedData<P>> handleMessage) {
if (processMessage(signedPayload, message)) {
gossipMessage.accept(signedPayload, message.getConnection().getPeer().getAddress());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is reworked as per:
private

void processMessage(
final Message message,
final SignedData

signedPayload,
final Consumer<SignedData

> handleMessage) {
if (processMessage(signedPayload, message)) {
gossiper.gossipMessage(signedPayload.getSignature(),
message.getData(),
signedPayload.getSender(),
signedPayload.getSender(), message.getConnection().getPeer().getAddress());
handleMessage.accept(signedPayload);
}
}

The gossip Biconsumer can be removed, and the msg specific handlers in Gossiper can be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is an improvement. There's nothing wrong with using a Biconsumer. The suggested version makes using the Gossiper require additional co-ordination and moves the responsibility for identifying the message and it's signer to the invoker which is worse encapsulation.

@Errorific Errorific force-pushed the feature/NC-1909.ibft_gossip_2 branch 2 times, most recently from 667f9cd to e819d1f Compare January 9, 2019 01:59
Copy link
Contributor

@CjHare CjHare left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Errorific Errorific merged commit bd9ffac into PegaSysEng:master Jan 9, 2019
@Errorific Errorific deleted the feature/NC-1909.ibft_gossip_2 branch January 9, 2019 04:40
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants