func (r *round3) BroadcastContent() round.BroadcastContent {
	return &broadcast3{
		VSSPolynomial:      polynomial.EmptyExponent(r.Group()),
		SchnorrCommitments: zksch.EmptyCommitment(r.Group()),
		ElGamalPublic:      r.Group().NewPoint(),
	}
}
BroadcastContent implements round.BroadcastRound.
package keygen
import (
	"errors"
	"fmt"
	"github.com/cronokirby/safenum"
	"github.com/taurusgroup/multi-party-sig/internal/round"
	"github.com/taurusgroup/multi-party-sig/internal/types"
	"github.com/taurusgroup/multi-party-sig/pkg/hash"
	"github.com/taurusgroup/multi-party-sig/pkg/math/curve"
	"github.com/taurusgroup/multi-party-sig/pkg/math/polynomial"
	"github.com/taurusgroup/multi-party-sig/pkg/paillier"
	"github.com/taurusgroup/multi-party-sig/pkg/party"
	"github.com/taurusgroup/multi-party-sig/pkg/pedersen"
	zkmod "github.com/taurusgroup/multi-party-sig/pkg/zk/mod"
	zkprm "github.com/taurusgroup/multi-party-sig/pkg/zk/prm"
	zksch "github.com/taurusgroup/multi-party-sig/pkg/zk/sch"
)
var _ round.Round = (*round3)(nil)
type round3 struct {
	*round2
	SchnorrCommitments map[party.ID]*zksch.Commitment  
}
type broadcast3 struct {
	round.NormalBroadcastContent
	RID types.RID
	C   types.RID
	VSSPolynomial *polynomial.Exponent
	SchnorrCommitments *zksch.Commitment
	ElGamalPublic      curve.Point
	N *safenum.Modulus
	S *safenum.Nat
	T *safenum.Nat
	Decommitment hash.Decommitment
}
func (r *round3) StoreBroadcastMessage(msg round.Message) error {
	from := msg.From
	body, ok := msg.Content.(*broadcast3)
	if !ok || body == nil {
		return round.ErrInvalidContent
	}
	if body.N == nil || body.S == nil || body.T == nil || body.VSSPolynomial == nil {
		return round.ErrNilFields
	}
	if err := body.RID.Validate(); err != nil {
		return fmt.Errorf("rid: %w", err)
	}
	if err := body.C.Validate(); err != nil {
		return fmt.Errorf("chainkey: %w", err)
	}
	if err := body.Decommitment.Validate(); err != nil {
		return err
	}
	VSSPolynomial := body.VSSPolynomial
	if !(r.VSSSecret.Constant().IsZero() == VSSPolynomial.IsConstant) {
		return errors.New("vss polynomial has incorrect constant")
	}
	if VSSPolynomial.Degree() != r.Threshold() {
		return errors.New("vss polynomial has incorrect degree")
	}
	if err := paillier.ValidateN(body.N); err != nil {
		return err
	}
	if err := pedersen.ValidateParameters(body.N, body.S, body.T); err != nil {
		return err
	}
	if !r.HashForID(from).Decommit(r.Commitments[from], body.Decommitment,
		body.RID, body.C, VSSPolynomial, body.SchnorrCommitments, body.ElGamalPublic, body.N, body.S, body.T) {
		return errors.New("failed to decommit")
	}
	r.RIDs[from] = body.RID
	r.ChainKeys[from] = body.C
	r.NModulus[from] = body.N
	r.S[from] = body.S
	r.T[from] = body.T
	r.PaillierPublic[from] = paillier.NewPublicKey(body.N)
	r.VSSPolynomials[from] = body.VSSPolynomial
	r.SchnorrCommitments[from] = body.SchnorrCommitments
	r.ElGamalPublic[from] = body.ElGamalPublic
	return nil
}
func (round3) VerifyMessage(round.Message) error { return nil }
func (round3) StoreMessage(round.Message) error { return nil }
func (r *round3) Finalize(out chan<- *round.Message) (round.Session, error) {
	chainKey := r.PreviousChainKey
	if chainKey == nil {
		chainKey = types.EmptyRID()
		for _, j := range r.PartyIDs() {
			chainKey.XOR(r.ChainKeys[j])
		}
	}
	rid := types.EmptyRID()
	for _, j := range r.PartyIDs() {
		rid.XOR(r.RIDs[j])
	}
	h := r.Hash()
	_ = h.WriteAny(rid, r.SelfID())
	mod := zkmod.NewProof(h.Clone(), zkmod.Private{
		P:   r.PaillierSecret.P(),
		Q:   r.PaillierSecret.Q(),
		Phi: r.PaillierSecret.Phi(),
	}, zkmod.Public{N: r.NModulus[r.SelfID()]}, r.Pool)
	prm := zkprm.NewProof(zkprm.Private{
		Lambda: r.PedersenSecret,
		Phi:    r.PaillierSecret.Phi(),
		P:      r.PaillierSecret.P(),
		Q:      r.PaillierSecret.Q(),
	}, h.Clone(), zkprm.Public{N: r.NModulus[r.SelfID()], S: r.S[r.SelfID()], T: r.T[r.SelfID()]}, r.Pool)
	if err := r.BroadcastMessage(out, &broadcast4{
		Mod: mod,
		Prm: prm,
	}); err != nil {
		return r, err
	}
	for _, j := range r.OtherPartyIDs() {
		share := r.VSSSecret.Evaluate(j.Scalar(r.Group()))
		C, _ := r.PaillierPublic[j].Enc(curve.MakeInt(share))
		err := r.SendMessage(out, &message4{
			Share: C,
		}, j)
		if err != nil {
			return r, err
		}
	}
	r.UpdateHashState(rid)
	return &round4{
		round3:   r,
		RID:      rid,
		ChainKey: chainKey,
	}, nil
}
func (round3) MessageContent() round.Content { return nil }
func (broadcast3) RoundNumber() round.Number { return 3 }