Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Malleability] Header #7100

Open
wants to merge 11 commits into
base: feature/malleability
Choose a base branch
from

Conversation

tim-barry
Copy link
Contributor

@tim-barry tim-barry commented Feb 27, 2025

Updates the Header type to make it non-malleable, by moving ProposerSigData field out of the Header to the new Proposal/BlockProposal types. Header.ID() will continue to return the same values as before this change.

Proposal is a new distinct type, used for proposing new blocks and receiving/verifying incoming proposed blocks from the network. It is an internal type corresponding to messages.BlockProposal/messages.ClusterBlockProposal, containing the header/block and associated ProposerSigData. The main changes associated with this are in the Compliance Core, consensus/collection Builder, and MessageHub; as well as adding some new conversion functions and unit test fixtures.

This PR preserves the "body" intermediate type used to calculate the Header ID, which converts the Timestamp to unix time (necessary because time.Time is not RLP-encodable and therefore malleable) and flattens LastViewTC into an ID, and splits it out into an explicit type so that it can be used in tests (TestHeaderFingerprint).
Various serialization methods and their tests are also preserved (TODO: discuss whether to remove JSON and/or Msgpack), as well as the Fingerprint method which is used to test RLP marshaling/unmarshaling.

Closes #6656

Base automatically changed from yurii/malleability-check-test to feature/malleability March 3, 2025 10:47
@tim-barry tim-barry force-pushed the tim/6656-header-id-malleability branch from e9419ef to cff44df Compare March 4, 2025 01:30
@codecov-commenter
Copy link

codecov-commenter commented Mar 4, 2025

Codecov Report

Attention: Patch coverage is 50.75075% with 164 lines in your changes missing coverage. Please review.

Project coverage is 41.15%. Comparing base (9ce4635) to head (349653b).
Report is 28 commits behind head on feature/malleability.

Files with missing lines Patch % Lines
consensus/hotstuff/model/proposal.go 0.00% 22 Missing ⚠️
module/buffer/pending_blocks.go 0.00% 22 Missing ⚠️
module/buffer/pending_cluster_blocks.go 0.00% 22 Missing ⚠️
utils/unittest/fixtures.go 0.00% 22 Missing ⚠️
module/mock/pending_block_buffer.go 0.00% 12 Missing ⚠️
module/mock/pending_cluster_block_buffer.go 0.00% 12 Missing ⚠️
consensus/hotstuff/notifications/telemetry.go 0.00% 8 Missing ⚠️
model/flow/header.go 30.00% 7 Missing ⚠️
module/mock/builder.go 0.00% 6 Missing ⚠️
cmd/consensus/main.go 0.00% 5 Missing ⚠️
... and 12 more
Additional details and impacted files
@@                   Coverage Diff                    @@
##           feature/malleability    #7100      +/-   ##
========================================================
+ Coverage                 41.12%   41.15%   +0.03%     
========================================================
  Files                      2097     2135      +38     
  Lines                    184820   188801    +3981     
========================================================
+ Hits                      76008    77709    +1701     
- Misses                   102473   104585    +2112     
- Partials                   6339     6507     +168     
Flag Coverage Δ
unittests 41.15% <50.75%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

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

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Prepare for creation of new "Proposal" type used to store the ProposerSigData
@tim-barry tim-barry force-pushed the tim/6656-header-id-malleability branch from cff44df to a11f637 Compare March 12, 2025 20:37
@tim-barry tim-barry marked this pull request as ready for review March 12, 2025 20:50
@tim-barry tim-barry requested a review from a team as a code owner March 12, 2025 20:50
@tim-barry
Copy link
Contributor Author

I've determined at least some of the failing tests are due to a missing proposer signature in the BlockResponse to a RangeRequest, in the synchronization engine.

filteredBlocks = append(filteredBlocks, &messages.BlockProposal{Block: block})

The blocks that are requested and synced then go through all the same logic as new block proposals, so their proposer signature is checked and found to be missing.

Appears in logs as [...] "error":"invalid proposal {ID} at view 1: invalid proposer signature: invalid vote at view 1 for block {ID}: could not split signature for block {ID}: invalid sig data length 0: signature's binary format is invalid","time":"2025-03-14T18:17:22Z","message":"received invalid block from other node (potential slashing evidence?)"}

Copy link
Member

@durkmurder durkmurder left a comment

Choose a reason for hiding this comment

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

Very nice, great work. I think there are some open questions how do we deal with syncing of blocks and recovery, most likely we will need to store the signature either way but I think we should leave this for another PR and have a separate discussion about this.

tim-barry and others added 2 commits March 17, 2025 10:59
Co-authored-by: Yurii Oleksyshyn <[email protected]>
Condense fingerprint code (as part of ID generation).
Apparent use case of fingerprint test now covered by the Malleability test.
see #7100 (comment)

Co-authored-by: Yurii Oleksyshyn <[email protected]>
proposal := messages.NewClusterBlockProposal(&block)
hotstuffProposal := model.SignedProposalFromFlow(block.Header)
proposal := unittest.ClusterProposalFromBlock(&block)
proposalMsg := messages.ClusterBlockProposalFrom(proposal) // TODO(tim) - unittest naming
Copy link
Member

Choose a reason for hiding this comment

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

Just adding a comment so we don't lost the TODO in a big diff

@@ -48,7 +48,6 @@ func BlockHeaderToMessage(
ParentVoterIds: parentVoterIds,
ParentVoterSigData: h.ParentVoterSigData,
ProposerId: h.ProposerID[:],
ProposerSigData: h.ProposerSigData,
Copy link
Member

Choose a reason for hiding this comment

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

Removing the signature field is a breaking API change.

We should minimally mark it as deprecated in the API docs (here is an example PR doing that: onflow/flow#1558). May need a more considered plan on how to deal with this if there is any substantial use of this field in the API already. If we end up merging this PR without fully addressing this, could you make an issue to address this under the Malleability tracker please.

fyi @peterargue

Copy link
Member

Choose a reason for hiding this comment

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

We have decided to store the proposer signature for all node roles, at least for this round of changes. Given that, we can simply include the proposer signature here again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants