Files
threshold/protocols/cmp/sign/round1.go
zeekay b41c78f5b3 round: rename Helper to Base — name the value, not the laziness
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.
2026-06-01 00:26:33 -07:00

110 lines
3.0 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 (
"crypto/rand"
"github.com/luxfi/threshold/internal/round"
"github.com/luxfi/threshold/pkg/math/curve"
"github.com/luxfi/threshold/pkg/math/sample"
"github.com/luxfi/threshold/pkg/paillier"
"github.com/luxfi/threshold/pkg/party"
"github.com/luxfi/threshold/pkg/pedersen"
zkenc "github.com/luxfi/threshold/pkg/zk/enc"
)
var _ round.Round = (*round1)(nil)
type round1 struct {
*round.Base
PublicKey curve.Point
SecretECDSA curve.Scalar
SecretPaillier *paillier.SecretKey
Paillier map[party.ID]*paillier.PublicKey
Pedersen map[party.ID]*pedersen.Parameters
ECDSA map[party.ID]curve.Point
Message []byte
}
// VerifyMessage implements round.Round.
func (*round1) VerifyMessage(round.Message) error { return nil }
// StoreMessage implements round.Round.
func (*round1) StoreMessage(round.Message) error { return nil }
// Finalize implements round.Round
//
// - sample kᵢ, γᵢ <- 𝔽,
// - Γᵢ = [γᵢ]⋅G
// - Gᵢ = Encᵢ(γᵢ;νᵢ)
// - Kᵢ = Encᵢ(kᵢ;ρᵢ)
//
// NOTE
// The protocol instructs us to broadcast Kᵢ and Gᵢ, but the protocol we implement
// cannot handle identify aborts since we are in a point to point model.
// We do as described in [LN18].
//
// In the next round, we send a hash of all the {Kⱼ,Gⱼ}ⱼ.
// In two rounds, we compare the hashes received and if they are different then we abort.
func (r *round1) Finalize(out chan<- *round.Message) (round.Session, error) {
// γᵢ <- 𝔽,
// Γᵢ = [γᵢ]⋅G
GammaShare, BigGammaShare := sample.ScalarPointPair(rand.Reader, r.Group())
// Gᵢ = Encᵢ(γᵢ;νᵢ)
G, GNonce := r.Paillier[r.SelfID()].Enc(curve.MakeInt(GammaShare))
// kᵢ <- 𝔽,
KShare := sample.Scalar(rand.Reader, r.Group())
// Kᵢ = Encᵢ(kᵢ;ρᵢ)
K, KNonce := r.Paillier[r.SelfID()].Enc(curve.MakeInt(KShare))
otherIDs := r.OtherPartyIDs()
broadcastMsg := broadcast2{K: K, G: G}
if err := r.BroadcastMessage(out, &broadcastMsg); err != nil {
return r, err
}
errors := r.Pool.Parallelize(len(otherIDs), func(i int) interface{} {
j := otherIDs[i]
proof := zkenc.NewProof(r.Group(), r.HashForID(r.SelfID()), zkenc.Public{
K: K,
Prover: r.Paillier[r.SelfID()],
Aux: r.Pedersen[j],
}, zkenc.Private{
K: curve.MakeInt(KShare),
Rho: KNonce,
})
err := r.SendMessage(out, &message2{
ProofEnc: proof,
}, j)
if err != nil {
return err
}
return nil
})
for _, err := range errors {
if err != nil {
return r, err.(error)
}
}
return &round2{
round1: r,
K: map[party.ID]*paillier.Ciphertext{r.SelfID(): K},
G: map[party.ID]*paillier.Ciphertext{r.SelfID(): G},
BigGammaShare: map[party.ID]curve.Point{r.SelfID(): BigGammaShare},
GammaShare: curve.MakeInt(GammaShare),
KShare: KShare,
KNonce: KNonce,
GNonce: GNonce,
}, nil
}
// MessageContent implements round.Round.
func (*round1) MessageContent() round.Content { return nil }
// Number implements round.Round.
func (*round1) Number() round.Number { return 1 }