mirror of
https://github.com/luxfi/threshold.git
synced 2026-10-30 15:15:53 +00:00
round.Helper was the canonical anti-pattern: a bare-noun
qualifier-name that told you nothing about what the type does. The
type is the embeddable Session implementation that protocol round
structs anchor on — its VALUE is "the base every round builds on".
Rename it to that.
type Helper struct { ... } → type Base struct { ... }
func (h *Helper) ... → func (h *Base) ...
func NewSession(...) (*Helper, error) → (*Base, error)
Output { *Helper } → Output { *Base }
Abort { *Helper } → Abort { *Base }
round.Helper → round.Base (18 files)
Helper: helper → Base: helper (struct literal init)
r.Helper.X / r.Helper → r.Base.X / r.Base (field access)
internal/round/helper.go → base.go
internal/round/helper_test.go → base_test.go
Forward-only — no type alias, no deprecation. The Go FAQ pointer-
receiver consistency landed in the prior commit (bf88f5a) so the
method set is already aligned; this commit only renames the type.
Build + vet clean; round / CMP keygen smoke / FROST keygen all
PASS unchanged.
148 lines
3.8 KiB
Go
148 lines
3.8 KiB
Go
package reshare
|
|
|
|
import (
|
|
"crypto/rand"
|
|
|
|
"github.com/luxfi/threshold/internal/round"
|
|
"github.com/luxfi/threshold/internal/types"
|
|
"github.com/luxfi/threshold/pkg/math/curve"
|
|
"github.com/luxfi/threshold/pkg/math/polynomial"
|
|
"github.com/luxfi/threshold/pkg/math/sample"
|
|
"github.com/luxfi/threshold/pkg/party"
|
|
"github.com/luxfi/threshold/protocols/lss/config"
|
|
)
|
|
|
|
// round1 initiates resharing by generating new polynomial shares
|
|
type round1 struct {
|
|
*round.Base
|
|
|
|
oldConfig *config.Config
|
|
newParticipants []party.ID
|
|
newThreshold int
|
|
inOldGroup bool
|
|
inNewGroup bool
|
|
|
|
// Polynomial for resharing (only for old parties)
|
|
poly *polynomial.Polynomial
|
|
|
|
// Chain key for new randomness
|
|
chainKey types.RID
|
|
}
|
|
|
|
// broadcast1 contains reshare commitments
|
|
type broadcast1 struct {
|
|
round.NormalBroadcastContent
|
|
|
|
// Commitments to reshare polynomial - g^f(j) for each new party j
|
|
Commitments map[party.ID]curve.Point
|
|
|
|
// Chain key for randomness
|
|
ChainKey types.RID
|
|
|
|
// Generation number
|
|
Generation uint64
|
|
}
|
|
|
|
// Number implements round.Round
|
|
func (r *round1) Number() round.Number {
|
|
return 1
|
|
}
|
|
|
|
// BroadcastContent implements round.BroadcastRound
|
|
func (r *round1) BroadcastContent() round.BroadcastContent {
|
|
return &broadcast1{}
|
|
}
|
|
|
|
// MessageContent implements round.Round
|
|
func (r *round1) MessageContent() round.Content {
|
|
return nil // No P2P messages in round 1
|
|
}
|
|
|
|
// RoundNumber implements round.Content
|
|
func (broadcast1) RoundNumber() round.Number {
|
|
return 1
|
|
}
|
|
|
|
// VerifyMessage implements round.Round
|
|
func (r *round1) VerifyMessage(_ round.Message) error {
|
|
return nil // No P2P messages
|
|
}
|
|
|
|
// StoreMessage implements round.Round
|
|
func (r *round1) StoreMessage(_ round.Message) error {
|
|
return nil // No P2P messages
|
|
}
|
|
|
|
// Finalize implements round.Round
|
|
func (r *round1) Finalize(out chan<- *round.Message) (round.Session, error) {
|
|
// Only old parties generate polynomials
|
|
if r.inOldGroup {
|
|
// Generate polynomial with our current share as constant term
|
|
// This preserves the group's public key
|
|
r.poly = polynomial.NewPolynomial(r.Group(), r.newThreshold-1, r.oldConfig.ECDSA)
|
|
|
|
// Generate new chain key
|
|
chainKey, err := types.NewRID(rand.Reader)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
r.chainKey = chainKey
|
|
|
|
// Create commitments for each new party
|
|
commitments := make(map[party.ID]curve.Point)
|
|
for _, j := range r.newParticipants {
|
|
x := j.Scalar(r.Group())
|
|
share := r.poly.Evaluate(x)
|
|
commitments[j] = share.ActOnBase()
|
|
}
|
|
|
|
// Broadcast commitments
|
|
if err := r.BroadcastMessage(out, &broadcast1{
|
|
Commitments: commitments,
|
|
ChainKey: chainKey,
|
|
Generation: r.oldConfig.Generation + 1,
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
// New parties just generate a random polynomial for blinding
|
|
secret := sample.Scalar(rand.Reader, r.Group())
|
|
r.poly = polynomial.NewPolynomial(r.Group(), r.newThreshold-1, secret)
|
|
|
|
// Generate chain key
|
|
chainKey, err := types.NewRID(rand.Reader)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
r.chainKey = chainKey
|
|
|
|
// Create dummy commitments (new parties don't contribute to resharing)
|
|
commitments := make(map[party.ID]curve.Point)
|
|
for _, j := range r.newParticipants {
|
|
commitments[j] = r.Group().NewPoint() // Identity element
|
|
}
|
|
|
|
// Broadcast empty commitments
|
|
if err := r.BroadcastMessage(out, &broadcast1{
|
|
Commitments: commitments,
|
|
ChainKey: chainKey,
|
|
Generation: r.oldConfig.Generation + 1,
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return &round2{
|
|
round1: r,
|
|
commitments: make(map[party.ID]map[party.ID]curve.Point),
|
|
chainKeys: make(map[party.ID]types.RID),
|
|
shares: make(map[party.ID]curve.Scalar),
|
|
}, nil
|
|
}
|
|
|
|
// StoreBroadcastMessage implements round.BroadcastRound
|
|
func (r *round1) StoreBroadcastMessage(_ round.Message) error {
|
|
// Messages stored in round2
|
|
return nil
|
|
}
|