Files
threshold/protocols/cmp/sign/round5.go
zeekay bf88f5a56d round: pointer receivers on trivial round methods
VerifyMessage/StoreMessage/MessageContent/Number/BroadcastContent on
round structs were value receivers. Go FAQ: "if any method on T takes
*T, all methods should take *T." Finalize already takes *T (it mutates
round state) so the others should too. Aligns the method set, removes
silent struct-copies on every dispatch, and prevents future drift
where a value-receiver method accidentally observes pre-Finalize
state. No behavior change — all current methods are no-ops or return
constants.

Touched: round.Abort, round.Output, all CMP keygen/presign/sign rounds,
all Doerner keygen/sign rounds, all FROST keygen/sign rounds, xor
example. Build + vet clean; CMP/FROST/Doerner -race tests PASS.
2026-06-01 00:07:58 -07:00

100 lines
2.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package sign
import (
"errors"
"github.com/luxfi/threshold/internal/round"
"github.com/luxfi/threshold/pkg/ecdsa"
"github.com/luxfi/threshold/pkg/math/curve"
"github.com/luxfi/threshold/pkg/party"
)
var _ round.Round = (*round5)(nil)
type round5 struct {
*round4
// SigmaShares[j] = σⱼ = m⋅kⱼ + χⱼ⋅R|ₓ
SigmaShares map[party.ID]curve.Scalar
// Delta = δ = ∑ⱼ δⱼ
// computed from received shares
Delta curve.Scalar
// BigDelta = Δ = ∑ⱼ Δⱼ
BigDelta curve.Point
// R = [δ⁻¹] Γ
BigR curve.Point
// R = R|ₓ
R curve.Scalar
}
type broadcast5 struct {
round.NormalBroadcastContent
SigmaShare curve.Scalar
}
// StoreBroadcastMessage implements round.BroadcastRound.
//
// - save σⱼ
func (r *round5) StoreBroadcastMessage(msg round.Message) error {
body, ok := msg.Content.(*broadcast5)
if !ok || body == nil {
return round.ErrInvalidContent
}
if body.SigmaShare.IsZero() {
return round.ErrNilFields
}
r.SigmaShares[msg.From] = body.SigmaShare
return nil
}
// VerifyMessage implements round.Round.
func (*round5) VerifyMessage(round.Message) error { return nil }
// StoreMessage implements round.Round.
func (*round5) StoreMessage(round.Message) error { return nil }
// Finalize implements round.Round
//
// - compute σ = ∑ⱼ σⱼ
// - verify signature.
func (r *round5) Finalize(chan<- *round.Message) (round.Session, error) {
// compute σ = ∑ⱼ σⱼ
Sigma := r.Group().NewScalar()
for _, j := range r.PartyIDs() {
Sigma.Add(r.SigmaShares[j])
}
signature := &ecdsa.Signature{
R: r.BigR,
S: Sigma,
}
if !signature.Verify(r.PublicKey, r.Message) {
return r.AbortRound(errors.New("failed to validate signature")), nil
}
return r.ResultRound(signature), nil
}
// MessageContent implements round.Round.
func (r *round5) MessageContent() round.Content { return nil }
// RoundNumber implements round.Content.
func (broadcast5) RoundNumber() round.Number { return 5 }
// BroadcastContent implements round.BroadcastRound.
func (r *round5) BroadcastContent() round.BroadcastContent {
return &broadcast5{
SigmaShare: r.Group().NewScalar(),
}
}
// Number implements round.Round.
func (*round5) Number() round.Number { return 5 }