From 7644075f55224c639d0dc6b375a039254987ab75 Mon Sep 17 00:00:00 2001 From: frozen <355847+Frozen@users.noreply.github.com> Date: Wed, 5 Aug 2026 15:45:37 -0400 Subject: [PATCH] consensus: preserve richer commit bitmap --- consensus/commit_bitmap.go | 55 ++++++++++++++++++++++++++++ consensus/commit_bitmap_test.go | 63 +++++++++++++++++++++++++++++++++ consensus/validator.go | 14 ++++---- 3 files changed, 124 insertions(+), 8 deletions(-) create mode 100644 consensus/commit_bitmap.go create mode 100644 consensus/commit_bitmap_test.go diff --git a/consensus/commit_bitmap.go b/consensus/commit_bitmap.go new file mode 100644 index 0000000000..5633838f71 --- /dev/null +++ b/consensus/commit_bitmap.go @@ -0,0 +1,55 @@ +package consensus + +import ( + "math/bits" + + "github.com/harmony-one/harmony/crypto/bls" +) + +// isMoreCompleteCommitPayload reports whether candidate has strictly more +// participating committee slots than current. Both payloads must use the same +// canonical signature-and-bitmap encoding; equal signer counts keep current. +func isMoreCompleteCommitPayload(current, candidate []byte, participantCount int) bool { + if !hasCanonicalCommitBitmap(current, participantCount) || + !hasCanonicalCommitBitmap(candidate, participantCount) { + return false + } + return commitPayloadSignerCount(candidate, participantCount) > + commitPayloadSignerCount(current, participantCount) +} + +// hasCanonicalCommitBitmap validates only the payload's structural encoding: +// its length must match one BLS signature followed by one bit per committee +// slot, and any unused high bits in the last bitmap byte must be zero. It does +// not verify the BLS signature or weighted quorum. +func hasCanonicalCommitBitmap(payload []byte, participantCount int) bool { + bitmapLen := (participantCount + 7) / 8 + if participantCount <= 0 || len(payload) != bls.BLSSignatureSizeInBytes+bitmapLen { + return false + } + if remainingBits := participantCount % 8; remainingBits != 0 { + validBits := byte(1< cur { - consensus.getLogger().Info().Hex("old", commitSigBitmap).Hex("new", recvMsg.Payload).Msg("[OnCommitted] Overriding commit signatures!!") - consensus.Blockchain().WriteCommitSig(blockObj.NumberU64(), recvMsg.Payload) + participantCount := len(consensus.decider().Participants()) + if err == nil && blk != nil && isMoreCompleteCommitPayload(commitSigBitmap, recvMsg.Payload, participantCount) { + consensus.getLogger().Info().Hex("old", commitSigBitmap).Hex("new", recvMsg.Payload).Msg("[OnCommitted] Overriding commit signatures!!") + if err := consensus.Blockchain().WriteCommitSig(blockObj.NumberU64(), recvMsg.Payload); err != nil { + consensus.getLogger().Warn().Err(err).Msg("[OnCommitted] failed writing richer commit sig") } }