mirror of
https://github.com/luxfi/threshold.git
synced 2026-10-30 15:15:53 +00:00
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.
100 lines
2.2 KiB
Go
100 lines
2.2 KiB
Go
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 }
|