Skip to content

Avoid mutating commit bitmap during certificate comparison - #5096

Open
Frozen wants to merge 1 commit into
harmony-one:devfrom
Frozen:fix/monotonic-commit-bitmap
Open

Avoid mutating commit bitmap during certificate comparison#5096
Frozen wants to merge 1 commit into
harmony-one:devfrom
Frozen:fix/monotonic-commit-bitmap

Conversation

@Frozen

@Frozen Frozen commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Problem

There is a potential order-dependent race between two valid commit certificates for the same block:

  1. the node already has an older certificate in the database;
  2. a newer COMMITTED message arrives with more signer slots;
  3. the node compares the two certificates before deciding which one to keep.

The existing comparison reuses the mutable bitmap decoded from the incoming message. To count signers in the stored certificate, it calls SetMask on that same bitmap object. This can overwrite the active incoming bitmap with the older stored bitmap while the aggregate signature still belongs to the incoming certificate.

For example:

  • stored certificate: 7/15 signer slots;
  • verified incoming certificate: 11/15 signer slots;
  • expected state: signature and bitmap from the 11/15 certificate;
  • possible old state: signature from 11/15, but bitmap changed back to 7/15 during comparison.

This is a logical state race caused by update ordering and shared mutable state, rather than a Go race-detector data race.

Fix

This PR makes certificate selection pure and monotonic:

  • compare the persisted and incoming payloads without mutating either bitmap;
  • accept a replacement only when the verified incoming certificate contains strictly more real committee slots;
  • keep the existing certificate when the incoming signer count is equal or lower;
  • reject incompatible payload lengths and non-canonical bitmap padding;
  • report database write failures instead of ignoring them.

After this change, the comparison itself cannot roll the active bitmap back to the older certificate, and the persisted certificate can only move to a more complete value.

The incoming certificate is still cryptographically and quorum-verified by the existing VerifyHeaderSignature path before this comparison runs.

Scope

This is a focused correctness fix based directly on dev. It does not change consensus quorum rules, BLS verification, wire formats, block timing, leader rotation, retry behavior, or feature activation epochs.

[Test]

  • make test
  • go test ./consensus -run '^TestIsMoreCompleteCommitPayload$' -count=1
  • git diff --check

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.

1 participant