Skip to content

Commit 1a9ba48

Browse files
committed
Address comments
1 parent e5b42b4 commit 1a9ba48

5 files changed

Lines changed: 34 additions & 30 deletions

File tree

signer/consensus_lock_e2e_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ func TestConsensusLockE2E(t *testing.T) {
9595

9696
// Test 6: After signing a PRECOMMIT for a different block, the lock should be updated
9797
// Simulate the lock update
98-
newLock := updateConsensusLock(signState.ConsensusLock, HRSKey{Height: 100, Round: 6, Step: stepPrecommit}, differentBlockPrecommit)
98+
newLock := nextConsensusLock(signState.ConsensusLock, HRSKey{Height: 100, Round: 6, Step: stepPrecommit}, differentBlockPrecommit)
9999
require.True(t, newLock.IsLocked(), "New lock should be active")
100100
require.Equal(t, int64(100), newLock.Height, "Lock should be at height 100")
101101
require.Equal(t, int64(6), newLock.Round, "Lock should be at round 6")
@@ -153,7 +153,7 @@ func TestConsensusLockRealWorldScenario(t *testing.T) {
153153
require.NoError(t, err, "Should allow PRECOMMIT for block B (releases lock)")
154154

155155
// After signing PRECOMMIT for block B, validator should be locked on block B
156-
newLock := updateConsensusLock(signState.ConsensusLock, HRSKey{Height: 100, Round: 6, Step: stepPrecommit}, blockBPrecommit)
156+
newLock := nextConsensusLock(signState.ConsensusLock, HRSKey{Height: 100, Round: 6, Step: stepPrecommit}, blockBPrecommit)
157157
require.True(t, newLock.IsLocked(), "Should be locked on block B")
158158
require.Equal(t, blockB, newLock.Value, "Lock should be on block B")
159159
require.Equal(t, int64(6), newLock.Round, "Lock should be at round 6")

signer/consensus_lock_simple_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func TestConsensusLockBasic(t *testing.T) {
6262
// Test updating lock on PRECOMMIT
6363
blockHash := []byte("new_block_hash_123456789012345678901234567890")[:32] // 32 bytes
6464
signBytes := createTestSignBytes(blockHash, stepPrecommit)
65-
signState.ConsensusLock = updateConsensusLock(
65+
signState.ConsensusLock = nextConsensusLock(
6666
signState.ConsensusLock, HRSKey{Height: 100, Round: 5, Step: stepPrecommit}, signBytes)
6767

6868
if !signState.ConsensusLock.IsLocked() {
@@ -174,14 +174,15 @@ func TestConsensusLockErrorTypes(t *testing.T) {
174174
}
175175

176176
// Test that we don't get an error for the same value
177-
sameBlockBytes := []byte("locked_block_hash_123456789012345678901234567890")
177+
sameBlockBytes := createTestSignBytes(lockedValue[:32], stepPrevote)
178178
err = signState.ValidateConsensusLock(HRSKey{Height: 100, Round: 6, Step: stepPrevote}, sameBlockBytes)
179179
if err != nil {
180180
t.Errorf("Expected no error for same value, got: %v", err)
181181
}
182182

183183
// Test that we don't get an error for different height
184-
err = signState.ValidateConsensusLock(HRSKey{Height: 101, Round: 5, Step: stepPrevote}, differentBlockBytes)
184+
differentHeightBytes := createTestSignBytes(differentBlockHash, stepPrevote)
185+
err = signState.ValidateConsensusLock(HRSKey{Height: 101, Round: 5, Step: stepPrevote}, differentHeightBytes)
185186
if err != nil {
186187
t.Errorf("Expected no error for different height, got: %v", err)
187188
}

signer/local_cosigner.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ func (cosigner *LocalCosigner) sign(req CosignerSignRequest) (CosignerSignRespon
306306
}
307307

308308
// Handle consensus lock updates according to Tendermint rules
309-
signStateConsensus.ConsensusLock = updateConsensusLock(ccs.lastSignState.ConsensusLock, hrst.HRSKey(), req.SignBytes)
309+
signStateConsensus.ConsensusLock = nextConsensusLock(ccs.lastSignState.ConsensusLock, hrst.HRSKey(), req.SignBytes)
310310

311311
err = ccs.lastSignState.Save(signStateConsensus, &cosigner.pendingDiskWG)
312312

signer/sign_state.go

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ func StepToType(step int8) cometproto.SignedMsgType {
101101
// ConsensusLock represents a Tendermint consensus lock on a specific value
102102
type ConsensusLock struct {
103103
Height int64 `json:"height"`
104-
Round int64 `json:"round"`
105-
Value []byte `json:"value,omitempty"` // nil for nil locked, non-nil for block locked
104+
Round int64 `json:"round"` // The round where we locked on this value (lockedRound)
105+
Value []byte `json:"value,omitempty"` // The value we're locked on (lockedValue)
106106
}
107107

108108
// IsLocked returns true if there is an active consensus lock
@@ -255,7 +255,7 @@ func (signState *SignState) blockDoubleSign(ssc SignStateConsensus) (*SignState,
255255
signState.VoteExtensionSignature = ssc.VoteExtensionSignature
256256

257257
// Handle consensus lock updates according to Tendermint rules
258-
signState.ConsensusLock = updateConsensusLock(signState.ConsensusLock, ssc.HRSKey(), ssc.SignBytes)
258+
signState.ConsensusLock = nextConsensusLock(signState.ConsensusLock, ssc.HRSKey(), ssc.SignBytes)
259259

260260
return signState.lockedCopy(), nil
261261
}
@@ -669,13 +669,13 @@ func (signState *SignState) ValidateConsensusLock(hrs HRSKey, signBytes []byte)
669669
return nil
670670
}
671671

672-
// For PROPOSAL and PREVOTE messages in rounds R' >= R, only allow signing for the locked value V
672+
// For PROPOSAL and PREVOTE messages in rounds R' >= locked_round, only allow signing for the locked value V
673+
// We use the stored round from the consensus lock for validation
673674
if (hrs.Step == stepPropose || hrs.Step == stepPrevote) && hrs.Round >= signState.ConsensusLock.Round {
674675
// Extract the block hash from the sign bytes to compare with the locked value
675-
blockHash := extractBlockHashFromSignBytes(signBytes, hrs.Step)
676-
if blockHash == nil {
677-
// If we can't extract the block hash, allow signing (fallback to existing behavior)
678-
return nil
676+
blockHash, err := extractBlockHashFromSignBytes(signBytes, hrs.Step)
677+
if err != nil {
678+
return fmt.Errorf("failed to extract block hash from sign bytes: %w", err)
679679
}
680680

681681
// Check if we're trying to sign a different value than what we're locked on
@@ -710,44 +710,44 @@ func (signState *SignState) ClearConsensusLock(hrs HRSKey) {
710710
}
711711

712712
// extractBlockHashFromSignBytes extracts the block hash from Tendermint sign bytes
713-
func extractBlockHashFromSignBytes(signBytes []byte, step int8) []byte {
713+
func extractBlockHashFromSignBytes(signBytes []byte, step int8) ([]byte, error) {
714714
if len(signBytes) == 0 {
715-
return nil
715+
return nil, fmt.Errorf("empty sign bytes")
716716
}
717717

718718
switch step {
719719
case stepPropose:
720720
// For PROPOSAL, extract block hash from CanonicalProposal
721721
var proposal cometproto.CanonicalProposal
722722
if err := protoio.UnmarshalDelimited(signBytes, &proposal); err != nil {
723-
return nil
723+
return nil, fmt.Errorf("failed to unmarshal proposal: %w", err)
724724
}
725725
blockID := proposal.GetBlockID()
726726
if blockID == nil {
727-
return nil
727+
return nil, fmt.Errorf("proposal has no block ID")
728728
}
729-
return blockID.GetHash()
729+
return blockID.GetHash(), nil
730730

731731
case stepPrevote, stepPrecommit:
732732
// For PREVOTE/PRECOMMIT, extract block hash from CanonicalVote
733733
var vote cometproto.CanonicalVote
734734
if err := protoio.UnmarshalDelimited(signBytes, &vote); err != nil {
735-
return nil
735+
return nil, fmt.Errorf("failed to unmarshal vote: %w", err)
736736
}
737737
blockID := vote.GetBlockID()
738738
if blockID == nil {
739-
return nil
739+
return nil, fmt.Errorf("vote has no block ID")
740740
}
741-
return blockID.GetHash()
741+
return blockID.GetHash(), nil
742742

743743
default:
744-
return nil
744+
return nil, fmt.Errorf("unknown step: %d", step)
745745
}
746746
}
747747

748-
// updateConsensusLock updates the consensus lock based on Tendermint rules
748+
// nextConsensusLock updates the consensus lock based on Tendermint rules
749749
// This is a helper function that can be used by both SignState and other components
750-
func updateConsensusLock(existingLock ConsensusLock, hrs HRSKey, signBytes []byte) ConsensusLock {
750+
func nextConsensusLock(existingLock ConsensusLock, hrs HRSKey, signBytes []byte) ConsensusLock {
751751
// Only update lock for PRECOMMIT steps (step 3)
752752
if hrs.Step != stepPrecommit {
753753
// For non-PRECOMMIT steps, only clear lock if moving to different height
@@ -759,8 +759,9 @@ func updateConsensusLock(existingLock ConsensusLock, hrs HRSKey, signBytes []byt
759759
}
760760

761761
// Extract the block hash from the sign bytes
762-
blockHash := extractBlockHashFromSignBytes(signBytes, hrs.Step)
763-
if blockHash == nil {
762+
blockHash, err := extractBlockHashFromSignBytes(signBytes, hrs.Step)
763+
if err != nil {
764+
// If we can't extract the block hash, return existing lock unchanged
764765
return existingLock
765766
}
766767

@@ -770,17 +771,19 @@ func updateConsensusLock(existingLock ConsensusLock, hrs HRSKey, signBytes []byt
770771
existingLock.IsLocked() &&
771772
!bytes.Equal(blockHash, existingLock.Value) {
772773
// Release old lock and set new lock on V'
774+
// Round is where we locked on this value (lockedRound)
773775
return ConsensusLock{
774776
Height: hrs.Height,
775-
Round: hrs.Round,
777+
Round: hrs.Round, // Round where we locked on this value
776778
Value: blockHash,
777779
}
778780
}
779781
if !existingLock.IsLocked() {
780782
// First lock for this height
783+
// Round is where we locked on this value (lockedRound)
781784
return ConsensusLock{
782785
Height: hrs.Height,
783-
Round: hrs.Round,
786+
Round: hrs.Round, // Round where we locked on this value
784787
Value: blockHash,
785788
}
786789
}

signer/threshold_validator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -975,7 +975,7 @@ func (pv *ThresholdValidator) Sign(
975975
}
976976

977977
// Handle consensus lock updates according to Tendermint rules
978-
newLss.SignStateConsensus.ConsensusLock = updateConsensusLock(
978+
newLss.SignStateConsensus.ConsensusLock = nextConsensusLock(
979979
css.lastSignState.ConsensusLock, block.HRSKey(), signBytes)
980980

981981
// Err will be present if newLss is not above high watermark

0 commit comments

Comments
 (0)