fix(error handling) - Do not ignore msg validation errors, refactor#615
fix(error handling) - Do not ignore msg validation errors, refactor#615oleg-ssvlabs wants to merge 5 commits into
Conversation
Greptile SummaryThis PR refactors QBFT justification handling by introducing two new helper methods (
Confidence Score: 5/5Safe to merge — no P0 or P1 issues found; all remaining feedback is style and test-coverage suggestions. All functional changes are pure refactors that preserve the existing behavior on the happy path and strictly improve error propagation. The two P2 comments (verbose naming, asymmetric test coverage) are non-blocking quality suggestions. No data integrity, security, or correctness issues were identified. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant caller as proposal.go / round_change.go
participant msg as qbft.Message
participant helper as processingMessagesFromSignedMessages
participant npm as NewProcessingMessage
caller->>msg: RoundChangeJustificationProcessingMessages()
msg->>msg: GetRoundChangeJustifications()
msg-->>caller: error (propagated, no longer silenced)
msg->>helper: processingMessagesFromSignedMessages(signedMsgs)
loop for each SignedSSVMessage
helper->>npm: NewProcessingMessage(signedMsg)
npm-->>helper: *ProcessingMessage or error
end
helper-->>msg: []*ProcessingMessage or error
msg-->>caller: []*ProcessingMessage or error
caller->>msg: PrepareJustificationProcessingMessages()
msg->>msg: GetPrepareJustifications()
msg-->>caller: error (propagated, no longer silenced)
msg->>helper: processingMessagesFromSignedMessages(signedMsgs)
loop for each SignedSSVMessage
helper->>npm: NewProcessingMessage(signedMsg)
npm-->>helper: *ProcessingMessage or error
end
helper-->>msg: []*ProcessingMessage or error
msg-->>caller: []*ProcessingMessage or error
Reviews (1): Last reviewed commit: "Do not ignore msg validation errors, ref..." | Re-trigger Greptile |
| @@ -0,0 +1,46 @@ | |||
| package qbft_test | |||
There was a problem hiding this comment.
we have qbft/spectest/tests/messages/round_change_justification_unmarshaling.go and qbft/spectest/tests/messages/prepare_justification_unmarshaling.go
what coverage do you add here?
There was a problem hiding this comment.
From what I can see, the existing spec tests cover unmarshalling justification bytes into []*SignedSSVMessage (via GetRoundChangeJustifications / GetPrepareJustifications called in Validate()). The new helper methods add a second step, converting []*SignedSSVMessage into []*ProcessingMessage by decoding SSVMessage.Data into a qbft.Message. The existing tests don't cover that path. The new unit tests cover both success and error cases for that conversion.
dab8fec
momosh-ssv
left a comment
There was a problem hiding this comment.
Non-blocking observations — the refactor itself looks correct and I don't see any behavioral regression (the ignored errors were already gated upstream by msg.Validate()).
| return errors.Wrap(err, "could not create ProcessingMessage from prepare message in round change justification") | ||
| } | ||
| prepareMsgs = append(prepareMsgs, msg) | ||
| prepareMsgs, err := msg.QBFTMessage.RoundChangeJustificationProcessingMessages() |
There was a problem hiding this comment.
Might be worth renaming prepareMsgs here (or adding a one-line comment). The source is RoundChangeJustificationProcessingMessages() but the variable is named prepareMsgs — correct per spec (RoundChange packs the prepare quorum into RoundChangeJustification), but the name/source mismatch is easy to misread. Pre-existing, but this was a natural moment to clarify.
Summary
Refactor QBFT justification decoding to stop suppressing extraction errors and centralize conversion of
justification messages into
ProcessingMessages.Problem
Several QBFT call sites were extracting justifications like this:
GetRoundChangeJustifications()/GetPrepareJustifications()[]*types.SignedSSVMessage*ProcessingMessageThe current code path relied on earlier
Validate()calls to catch malformed justification bytes, so this was notan active validation bypass today. But the error handling was non-local and brittle, and the conversion logic was
duplicated across proposal and round-change flows.
Changes
qbft.Message:RoundChangeJustificationProcessingMessages()PrepareJustificationProcessingMessages()[]*types.SignedSSVMessageinto[]*ProcessingMessageNewProcessingMessage(...)conversion pathWhy
This makes the invariant local at the point of use:
Tests
Added focused QBFT unit tests covering:
ProcessingMessages successfullyCloses https://github.com/ssvlabs/ssv-node-board/issues/845
Closes https://github.com/ssvlabs/ssv-node-board/issues/843