Skip to content

Commit 3591ceb

Browse files
committed
nits
1 parent 0349eb9 commit 3591ceb

File tree

2 files changed

+69
-22
lines changed

2 files changed

+69
-22
lines changed

x/fibre/validator/signature_set.go

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,6 @@ import (
99
core "github.com/cometbft/cometbft/types"
1010
)
1111

12-
var (
13-
// ErrNotEnoughSignatures indicates that not enough signatures were collected to meet the count threshold.
14-
ErrNotEnoughSignatures = fmt.Errorf("not enough signatures")
15-
// ErrNotEnoughVotingPower indicates that the collected signatures don't have sufficient voting power.
16-
ErrNotEnoughVotingPower = fmt.Errorf("not enough voting power")
17-
)
18-
1912
// SignatureSet collects and validates signatures from validators.
2013
// It is safe for concurrent use.
2114
type SignatureSet struct {
@@ -78,18 +71,42 @@ func (ss *SignatureSet) Done() <-chan struct{} {
7871
}
7972

8073
// Signatures returns all collected signatures if thresholds are met.
81-
// Returns [ErrNotEnoughSignatures] if count threshold is not met.
82-
// Returns [ErrNotEnoughVotingPower] if voting power threshold is not met.
74+
// Returns [NotEnoughSignaturesError] if either count or voting power threshold is not met.
75+
// The error contains the partially collected signatures and threshold information.
8376
func (ss *SignatureSet) Signatures() ([][]byte, error) {
8477
ss.mu.Lock()
8578
defer ss.mu.Unlock()
8679

87-
if len(ss.signatures) < ss.minRequiredSignatures {
88-
return nil, ErrNotEnoughSignatures
89-
}
90-
if ss.votingPower < ss.minRequiredVotingPower {
91-
return nil, ErrNotEnoughVotingPower
80+
countNotMet := len(ss.signatures) < ss.minRequiredSignatures
81+
powerNotMet := ss.votingPower < ss.minRequiredVotingPower
82+
if countNotMet || powerNotMet {
83+
return nil, &NotEnoughSignaturesError{
84+
Collected: ss.signatures,
85+
RequiredCount: ss.minRequiredSignatures,
86+
CollectedPower: ss.votingPower,
87+
RequiredPower: ss.minRequiredVotingPower,
88+
}
9289
}
9390

9491
return ss.signatures, nil
9592
}
93+
94+
// NotEnoughSignaturesError indicates that signature collection did not meet the required thresholds.
95+
// It contains the partially collected signatures and threshold information.
96+
type NotEnoughSignaturesError struct {
97+
Collected [][]byte
98+
RequiredCount int
99+
CollectedPower int64
100+
RequiredPower int64
101+
}
102+
103+
func (e *NotEnoughSignaturesError) Error() string {
104+
switch {
105+
case len(e.Collected) < e.RequiredCount:
106+
return fmt.Sprintf("not enough signatures: collected %d, required %d", len(e.Collected), e.RequiredCount)
107+
case e.CollectedPower < e.RequiredPower:
108+
return fmt.Sprintf("not enough voting power: collected %d, required %d", e.CollectedPower, e.RequiredPower)
109+
default:
110+
panic("unreachable")
111+
}
112+
}

x/fibre/validator/signature_set_test.go

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
func makeValidators(n int, votingPower int64) ([]*core.Validator, []ed25519.PrivKey) {
1616
validators := make([]*core.Validator, n)
1717
privKeys := make([]ed25519.PrivKey, n)
18-
for i := 0; i < n; i++ {
18+
for i := range n {
1919
privKeys[i] = ed25519.GenPrivKey()
2020
validators[i] = core.NewValidator(privKeys[i].PubKey(), votingPower)
2121
}
@@ -59,37 +59,67 @@ func TestSignatureSet(t *testing.T) {
5959
// 2/3 of 50 = 33 requiredVotingPower
6060
// 2/3 of 5 = 3 requiredCount
6161
// Add 3 signatures (30 voting power, meets count threshold of 3 but not voting power threshold of 33)
62-
for i := 0; i < 3; i++ {
62+
for i := range 3 {
6363
signature, err := s.privKeys[i].Sign(s.signBytes)
6464
require.NoError(t, err)
6565
require.NoError(t, s.sigSet.Add(s.validators[i], signature))
6666
}
6767

68+
// Check that Done() is NOT closed when thresholds are not met
69+
select {
70+
case <-s.sigSet.Done():
71+
t.Fatal("Done() should not be closed when thresholds are not met")
72+
default:
73+
}
74+
6875
sigs, err := s.sigSet.Signatures()
69-
require.ErrorIs(t, err, validator.ErrNotEnoughVotingPower)
7076
require.Nil(t, sigs)
77+
require.Error(t, err)
78+
79+
var sigErr *validator.NotEnoughSignaturesError
80+
require.ErrorAs(t, err, &sigErr)
81+
require.Len(t, sigErr.Collected, 3)
82+
require.Equal(t, int64(30), sigErr.CollectedPower)
83+
require.Equal(t, int64(33), sigErr.RequiredPower)
84+
require.Equal(t, 3, sigErr.RequiredCount)
85+
require.Contains(t, err.Error(), "not enough voting power")
7186
})
7287

7388
t.Run("NotEnoughSignatures", func(t *testing.T) {
7489
s := setupSignatureSet(5, 10, twoThirds, twoThirds)
7590

7691
// Add only 2 signatures (requiredCount = 3)
77-
for i := 0; i < 2; i++ {
92+
for i := range 2 {
7893
signature, err := s.privKeys[i].Sign(s.signBytes)
7994
require.NoError(t, err)
8095
require.NoError(t, s.sigSet.Add(s.validators[i], signature))
8196
}
8297

98+
// Check that Done() is NOT closed when thresholds are not met
99+
select {
100+
case <-s.sigSet.Done():
101+
t.Fatal("Done() should not be closed when thresholds are not met")
102+
default:
103+
}
104+
83105
sigs, err := s.sigSet.Signatures()
84-
require.ErrorIs(t, err, validator.ErrNotEnoughSignatures)
85106
require.Nil(t, sigs)
107+
require.Error(t, err)
108+
109+
var sigErr *validator.NotEnoughSignaturesError
110+
require.ErrorAs(t, err, &sigErr)
111+
require.Len(t, sigErr.Collected, 2)
112+
require.Equal(t, 3, sigErr.RequiredCount)
113+
require.Equal(t, int64(20), sigErr.CollectedPower)
114+
require.Equal(t, int64(33), sigErr.RequiredPower)
115+
require.Contains(t, err.Error(), "not enough signatures")
86116
})
87117

88118
t.Run("SuccessSequential", func(t *testing.T) {
89119
s := setupSignatureSet(5, 10, twoThirds, twoThirds)
90120

91121
// Add 4 signatures (40 voting power, meets both thresholds)
92-
for i := 0; i < 4; i++ {
122+
for i := range 4 {
93123
signature, err := s.privKeys[i].Sign(s.signBytes)
94124
require.NoError(t, err)
95125
require.NoError(t, s.sigSet.Add(s.validators[i], signature))
@@ -111,7 +141,7 @@ func TestSignatureSet(t *testing.T) {
111141
s := setupSignatureSet(10, 10, twoThirds, twoThirds)
112142

113143
var wg sync.WaitGroup
114-
for i := 0; i < 10; i++ {
144+
for i := range 10 {
115145
wg.Add(1)
116146
go func(idx int) {
117147
defer wg.Done()
@@ -150,7 +180,7 @@ func TestSignatureSet(t *testing.T) {
150180
s := setupSignatureSet(5, 10, half, half)
151181

152182
// Add 3 valid signatures (30 voting power, meets threshold of 25)
153-
for i := 0; i < 3; i++ {
183+
for i := range 3 {
154184
signature, err := s.privKeys[i].Sign(s.signBytes)
155185
require.NoError(t, err)
156186
require.NoError(t, s.sigSet.Add(s.validators[i], signature))

0 commit comments

Comments
 (0)