Skip to content

Conversation

@sstanculeanu
Copy link
Collaborator

Reasoning behind the pull request

  • implement equivalent messages filter on consensus topic, in order to stop further broadcasts of messages containing same block final info

Proposed changes

  • added filter for equivalent messages
  • added specific debugger

Testing procedure

  • with feat branch

Pre-requisites

Based on the Contributing Guidelines the PR author and the reviewers must check the following requirements are met:

  • was the PR targeted to the correct branch?
  • if this is a larger feature that probably needs more than one PR, is there a feat branch created?
  • if this is a feat branch merging, do all satellite projects have a proper tag inside go.mod?

@iulianpascalau iulianpascalau self-requested a review October 24, 2023 12:46

// EquivalentMessagesDebugger defines the specific debugger for equivalent messages
type EquivalentMessagesDebugger interface {
DisplayEquivalentMessagesStatistics(getDataHandler func() map[string]uint64)
Copy link
Contributor

Choose a reason for hiding this comment

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

let's make the signature more straightforward. Why not declare the function like

DisplayEquivalentMessagesStatistics(messages map[string]uint64)

Copy link
Collaborator Author

@sstanculeanu sstanculeanu Oct 24, 2023

Choose a reason for hiding this comment

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

I tried to avoid copying the map when we don't need the log.. with the function pointer approach, it is copied only when the debugger is active

wrk.mutEquivalentMessages.Lock()
defer wrk.mutEquivalentMessages.Unlock()

// if an equivalent message was seen before, return error to stop further broadcasts
Copy link
Contributor

Choose a reason for hiding this comment

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

slightly optimization for L743 - L49

numMessages := wrk.equivalentMessages[hdrHash]
wrk.equivalentMessages[hdrHash] = numMessages+1
if numMessages > 0 {
    return ErrEquivalentMessageAlreadyReceived
}

as this one does one read & one write on the map. The original code does 2 reads & one write

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

applied

wrk.mutEquivalentMessages.RLock()
defer wrk.mutEquivalentMessages.RUnlock()

equivalentMessagesCopy := make(map[string]uint64, len(wrk.equivalentMessages))
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

equivMsgFrom,
&p2pmocks.MessengerStub{},
)
assert.Equal(t, spos.ErrEquivalentMessageAlreadyReceived, err)
Copy link
Contributor

Choose a reason for hiding this comment

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

test also the inner counter? Or a special unit test for the reset & read of the counters?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

improved the test

@AdoAdoAdo AdoAdoAdo self-requested a review October 24, 2023 13:31
@codecov
Copy link

codecov bot commented Oct 25, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

❗ No coverage uploaded for pull request base (feat/equivalent-messages@8145826). Click here to learn what that means.

❗ Current head 918f099 differs from pull request most recent head c9fe2aa. Consider uploading reports for the commit c9fe2aa to get more accurate results

Additional details and impacted files
@@                     Coverage Diff                     @@
##             feat/equivalent-messages    #5666   +/-   ##
===========================================================
  Coverage                            ?   80.37%           
===========================================================
  Files                               ?      712           
  Lines                               ?    94410           
  Branches                            ?        0           
===========================================================
  Hits                                ?    75879           
  Misses                              ?    13223           
  Partials                            ?     5308           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

wrk.mutEquivalentMessages.Lock()
defer wrk.mutEquivalentMessages.Unlock()

delete(wrk.equivalentMessages, hdrHash)
Copy link
Contributor

Choose a reason for hiding this comment

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

I do not think this is the proper way to do this.
Reason: what happens in this scenario?

  1. receive the correct message
  2. receive the same block final info but for some reason checkConsensusMessageValidity returns an error. We delete the equivalent message for the hdrHash
  3. we receive the correct message again and we re-broadcast it

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

pushed

msgType := consensus.MessageType(cnsMsg.MsgType)

err = wrk.processEquivalentMessage(msgType, cnsMsg.BlockHeaderHash)
wrk.mutEquivalentMessages.Lock()
Copy link
Contributor

Choose a reason for hiding this comment

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

this solves the problem, hopefully, as it will only call once checkConsensusMessageValidity per round if the messages are correct and there are no edge cases of multiple broadcasts or message misses I've talked about.
However, I would extract L401-L422 in a new function: checkValidityAndProcessEquivalentMessages and use the defer mechanism for the mutex unlocking

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

updated as suggested

iulianpascalau
iulianpascalau previously approved these changes Nov 13, 2023
iulianpascalau
iulianpascalau previously approved these changes Dec 7, 2023
…nly when necessary + added equivalent message signature verification
…rsx/mx-chain-go into equivalent_messages_filter

# Conflicts:
#	cmd/node/config/enableEpochs.toml
#	common/enablers/enableEpochsHandler.go
#	common/enablers/enableEpochsHandler_test.go
#	common/enablers/epochFlags.go
#	common/interface.go
#	config/epochConfig.go
#	config/tomlConfig_test.go
#	consensus/spos/bls/blsSubroundsFactory.go
#	consensus/spos/bls/subroundStartRound.go
#	consensus/spos/bls/subroundStartRound_test.go
#	consensus/spos/errors.go
#	consensus/spos/interface.go
#	testscommon/enableEpochsHandlerMock/enableEpochsHandlerStub.go
line := []string{
hash,
fmt.Sprintf("%d", cnt),
fmt.Sprintf("%d", info.NumMessages),
Copy link
Contributor

Choose a reason for hiding this comment

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

this will need to display new fields, most importantly if any equivalent proof was validated, can be done on the next PR.

}

return nil
// TODO[Sorin]: after flag enabled, VerifySignature on previous hash, with the signature and bitmap from the proof on cnsMsg
Copy link
Contributor

Choose a reason for hiding this comment

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

verify on current header with the signature and bitmap from cnsMsg, but anyway would be removed in next PR.

@sstanculeanu sstanculeanu merged commit bd628de into feat/equivalent-messages Dec 21, 2023
@sstanculeanu sstanculeanu deleted the equivalent_messages_filter branch December 21, 2023 14:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants