Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions consensus/spos/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,10 @@ func (wrk *Worker) ProcessReceivedMessage(message p2p.MessageP2P, fromConnectedP

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

err = wrk.processEquivalentMessageUnprotected(msgType, cnsMsg.BlockHeaderHash)
if err != nil {
wrk.mutEquivalentMessages.Unlock()
return err
}

Expand All @@ -413,9 +415,11 @@ func (wrk *Worker) ProcessReceivedMessage(message p2p.MessageP2P, fromConnectedP

err = wrk.consensusMessageValidator.checkConsensusMessageValidity(cnsMsg, message.Peer())
if err != nil {
wrk.processInvalidEquivalentMessage(msgType, cnsMsg.BlockHeaderHash)
wrk.processInvalidEquivalentMessageUnprotected(msgType, cnsMsg.BlockHeaderHash)
wrk.mutEquivalentMessages.Unlock()
return err
}
wrk.mutEquivalentMessages.Unlock()

wrk.networkShardingCollector.UpdatePeerIDInfo(message.Peer(), cnsMsg.PubKey, wrk.shardCoordinator.SelfId())

Expand Down Expand Up @@ -729,17 +733,14 @@ func (wrk *Worker) ResetConsensusMessages() {
wrk.consensusMessageValidator.resetConsensusMessages()
}

func (wrk *Worker) processEquivalentMessage(msgType consensus.MessageType, blockHeaderHash []byte) error {
func (wrk *Worker) processEquivalentMessageUnprotected(msgType consensus.MessageType, blockHeaderHash []byte) error {
// early exit if the message is not with final info
if !wrk.consensusService.IsMessageWithFinalInfo(msgType) {
return nil
}

hdrHash := string(blockHeaderHash)

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

numMessages := wrk.equivalentMessages[hdrHash]
wrk.equivalentMessages[hdrHash] = numMessages + 1
Expand All @@ -750,16 +751,13 @@ func (wrk *Worker) processEquivalentMessage(msgType consensus.MessageType, block
return nil
}

func (wrk *Worker) processInvalidEquivalentMessage(msgType consensus.MessageType, blockHeaderHash []byte) {
func (wrk *Worker) processInvalidEquivalentMessageUnprotected(msgType consensus.MessageType, blockHeaderHash []byte) {
if !wrk.consensusService.IsMessageWithFinalInfo(msgType) {
return
}

hdrHash := string(blockHeaderHash)

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

}

Expand Down