Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
Signed-off-by: bytemare <[email protected]>
  • Loading branch information
bytemare committed Sep 3, 2024
1 parent df7407e commit 549391a
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 15 deletions.
12 changes: 6 additions & 6 deletions commitment.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func (c CommitmentList) Participants() []uint64 {
return out
}

// ParticipantsScalar returns the group.Scalar list of participant identifier in the list
// ParticipantsScalar returns the group.Scalar list of participant identifier in the list.
func (c CommitmentList) ParticipantsScalar() []*group.Scalar {
if len(c) == 0 {
return nil
Expand Down Expand Up @@ -321,11 +321,11 @@ func (c *Configuration) validateCommitmentListLength(commitments CommitmentList)
}

// ValidateCommitmentList returns an error if at least one of the following conditions is not met:
// - list length is within [threshold;max]
// - no signer identifier in commitments is 0
// - no singer identifier in commitments is > max signers
// - no duplicated in signer identifiers
// - all commitment signer identifiers are registered in the configuration
// - list length is within [threshold;max].
// - no signer identifier in commitments is 0.
// - no singer identifier in commitments is > max signers.
// - no duplicated in signer identifiers.
// - all commitment signer identifiers are registered in the configuration.
func (c *Configuration) ValidateCommitmentList(commitments CommitmentList) error {

Check failure on line 329 in commitment.go

View workflow job for this annotation

GitHub Actions / Lint / GolangCI-Lint

cognitive complexity 18 of func `(*Configuration).ValidateCommitmentList` is high (> 16) (gocognit)
if !c.verified || !c.keysVerified {
if err := c.Init(); err != nil {
Expand Down
1 change: 1 addition & 0 deletions encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func encodedLength(encID byte, g group.Group, other ...uint64) uint64 {
case encConf:
return 1 + 3*8 + eLen + other[0]
case encSigner:
_ = other[3]

Check failure on line 49 in encoding.go

View workflow job for this annotation

GitHub Actions / Lint / GolangCI-Lint

G602: slice index out of range (gosec)
return other[0] + 2 + 2 + 2 + other[1] + other[2] + other[3]

Check failure on line 50 in encoding.go

View workflow job for this annotation

GitHub Actions / Lint / GolangCI-Lint

G602: slice index out of range (gosec)
case encSigShare:
return 1 + 8 + sLen
Expand Down
3 changes: 2 additions & 1 deletion frost.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,8 @@ func (c *Configuration) ValidateKeyShare(keyShare *KeyShare) error {

if pk.Equal(keyShare.PublicKey) != 1 {
return errors.New(
"provided key share has a different public key than the one registered for that signer in the configuration",
"provided key share has a different public key than" +
"the one registered for that signer in the configuration",
)
}

Expand Down
20 changes: 14 additions & 6 deletions internal/lambda.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ import (

// Lambda derives the interpolating value for id in the polynomial made by the participant identifiers.
// This function assumes that:
// - id is non-nil and != 0
// - every scalar in participants is non-nil and != 0
// - there are no duplicates in participants
// - id is non-nil and != 0.
// - every scalar in participants is non-nil and != 0.
// - there are no duplicates in participants.
func Lambda(g group.Group, id uint64, participants []*group.Scalar) *group.Scalar {
sid := g.NewScalar().SetUInt64(id)
numerator := g.NewScalar().One()
Expand All @@ -39,6 +39,8 @@ func Lambda(g group.Group, id uint64, participants []*group.Scalar) *group.Scala
return numerator.Multiply(denominator.Invert())
}

// LambdaRegistry holds a signers pre-computed lambda values, indexed by the list of participants they are associated
// to. A sorted set of participants will yield the same lambda.
type LambdaRegistry map[string]*group.Scalar

const lambdaRegistryKeyDomainSeparator = "FROST-participants"
Expand All @@ -50,9 +52,9 @@ func lambdaRegistryKey(participants []uint64) string {

// New creates a new lambda and for the participant list for the participant id, and registers it.
// This function assumes that:
// - id is non-nil and != 0
// - every participant id is != 0
// - there are no duplicates in participants
// - id is non-nil and != 0.
// - every participant id is != 0.
// - there are no duplicates in participants.
func (l LambdaRegistry) New(g group.Group, id uint64, participants []uint64) *group.Scalar {
polynomial := secretsharing.NewPolynomialFromListFunc(g, participants, func(p uint64) *group.Scalar {
return g.NewScalar().SetUInt64(p)
Expand All @@ -63,11 +65,14 @@ func (l LambdaRegistry) New(g group.Group, id uint64, participants []uint64) *gr
return lambda
}

// Get returns the recorded lambda for the list of participants, or nil if it wasn't found.
func (l LambdaRegistry) Get(participants []uint64) *group.Scalar {
key := lambdaRegistryKey(participants)
return l[key]
}

// GetOrNew returns the recorded lambda for the list of participants, or created, records, and returns a new one if
// it wasn't found.
func (l LambdaRegistry) GetOrNew(g group.Group, id uint64, participants []uint64) *group.Scalar {
lambda := l.Get(participants)
if lambda == nil {
Expand All @@ -77,17 +82,20 @@ func (l LambdaRegistry) GetOrNew(g group.Group, id uint64, participants []uint64
return lambda
}

// Set records lambda for the given set of participants.
func (l LambdaRegistry) Set(participants []uint64, lambda *group.Scalar) {
key := lambdaRegistryKey(participants)
l[key] = lambda
}

// Delete deletes the lambda for the given set of participants.
func (l LambdaRegistry) Delete(participants []uint64) {
key := lambdaRegistryKey(participants)
l[key].Zero()
delete(l, key)
}

// Decode populates the receiver from the byte encoded serialization in data.
func (l LambdaRegistry) Decode(g group.Group, data []byte) error {
offset := 0
for offset < len(data) {
Expand Down
66 changes: 65 additions & 1 deletion tests/commitment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,35 @@ import (
"github.com/bytemare/frost"
)

func TestCommitment_Validate_InvalidConfiguration(t *testing.T) {
expectedErrorPrefix := "invalid group public key, the key is nil"
tt := &tableTest{
Ciphersuite: frost.Ristretto255,
threshold: 3,
maxSigners: 5,
}
configuration := &frost.Configuration{
Ciphersuite: tt.Ciphersuite,
Threshold: tt.threshold,
MaxSigners: tt.maxSigners,
GroupPublicKey: nil,
SignerPublicKeyShares: nil,
}

if err := configuration.ValidateCommitment(nil); err == nil ||
!strings.HasPrefix(err.Error(), expectedErrorPrefix) {
t.Fatalf("expected %q, got %q", expectedErrorPrefix, err)
}
}

func TestCommitment_Validate_NilCommitment(t *testing.T) {
expectedErrorPrefix := "the commitment list has a nil commitment"
tt := &tableTest{
Ciphersuite: frost.Ristretto255,
threshold: 3,
maxSigners: 4,
}
configuration, _ := fullSetup(t, tt)
configuration := makeConf(t, tt)

if err := configuration.ValidateCommitment(nil); err == nil ||
!strings.HasPrefix(err.Error(), expectedErrorPrefix) {
Expand Down Expand Up @@ -231,6 +252,27 @@ func TestCommitmentList_Sort(t *testing.T) {
})
}

func TestCommitmentList_Validate_InvalidConfiguration(t *testing.T) {
expectedErrorPrefix := "invalid group public key, the key is nil"
tt := &tableTest{
Ciphersuite: frost.Ristretto255,
threshold: 3,
maxSigners: 5,
}
configuration := &frost.Configuration{
Ciphersuite: tt.Ciphersuite,
Threshold: tt.threshold,
MaxSigners: tt.maxSigners,
GroupPublicKey: nil,
SignerPublicKeyShares: nil,
}

if err := configuration.ValidateCommitmentList(nil); err == nil ||
!strings.HasPrefix(err.Error(), expectedErrorPrefix) {
t.Fatalf("expected %q, got %q", expectedErrorPrefix, err)
}
}

func TestCommitmentList_Validate_NoCommitments(t *testing.T) {
expectedErrorPrefix := "commitment list is empty"
tt := &tableTest{
Expand Down Expand Up @@ -345,6 +387,28 @@ func TestCommitmentList_Validate_InvalidCommitment(t *testing.T) {
}
}

func TestCommitmentList_Validate_NilCommitment(t *testing.T) {
expectedErrorPrefix := "the commitment list has a nil commitment"
tt := &tableTest{
Ciphersuite: frost.Ristretto255,
threshold: 3,
maxSigners: 4,
}
configuration, signers := fullSetup(t, tt)
coms := make(frost.CommitmentList, len(signers))

for i, s := range signers {
coms[i] = s.Commit()
}

coms[2] = nil

if err := configuration.ValidateCommitmentList(coms); err == nil ||
!strings.HasPrefix(err.Error(), expectedErrorPrefix) {
t.Fatalf("expected %q, got %q", expectedErrorPrefix, err)
}
}

func TestCommitmentList_Validate_NotSorted(t *testing.T) {
expectedErrorPrefix := "commitment list is not sorted by signer identifiers"
tt := &tableTest{
Expand Down
31 changes: 30 additions & 1 deletion tests/encoding_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ func TestEncoding_Configuration_InvalidGroupPublicKey(t *testing.T) {
})
}

func TestEncoding_Configuration_InvalidPublicKeyShare(t *testing.T) {
func TestEncoding_Configuration_BadPublicKeyShare(t *testing.T) {
expectedErrorPrefix := "could not decode signer public key share for signer 1: "

testAll(t, func(t *testing.T, test *tableTest) {
Expand Down Expand Up @@ -407,6 +407,35 @@ func TestEncoding_Configuration_InvalidPublicKeyShare(t *testing.T) {
})
}

func TestEncoding_Configuration_InvalidPublicKeyShares(t *testing.T) {
expectedErrorPrefix := "invalid number of public keys (lower than threshold or above maximum)"

testAll(t, func(t *testing.T, test *tableTest) {
keyShares, groupPublicKey, _ := debug.TrustedDealerKeygen(
test.Ciphersuite,
nil,
test.threshold,
test.maxSigners,
)
publicKeyShares := getPublicKeyShares(keyShares)

configuration := &frost.Configuration{
Ciphersuite: test.Ciphersuite,
Threshold: test.threshold,
MaxSigners: test.maxSigners,
GroupPublicKey: groupPublicKey,
SignerPublicKeyShares: publicKeyShares,
}
configuration.SignerPublicKeyShares = configuration.SignerPublicKeyShares[:test.threshold-1]
encoded := configuration.Encode()

decoded := new(frost.Configuration)
if err := decoded.Decode(encoded); err == nil || !strings.HasPrefix(err.Error(), expectedErrorPrefix) {
t.Fatalf("expected %q, got %q", expectedErrorPrefix, err)
}
})
}

func TestEncoding_Configuration_CantVerify_InvalidPubKey(t *testing.T) {
expectedErrorPrefix := "invalid group public key, the key is the group generator (base element)"

Expand Down

0 comments on commit 549391a

Please sign in to comment.