func (h *Helper) BroadcastMessage(out chan<- *Message, broadcastContent Content) error {
	msg := &Message{
		From:      h.info.SelfID,
		Broadcast: true,
		Content:   broadcastContent,
	}
	select {
	case out <- msg:
		return nil
	default:
		return ErrOutChanFull
	}
}
BroadcastMessage constructs a Message from the broadcast Content, and sets the header correctly.
An error is returned if the message cannot be sent to the out channel.
package round
import (
	"errors"
	"fmt"
	"math"
	"sync"
	"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/party"
	"github.com/taurusgroup/multi-party-sig/pkg/pool"
)
type Helper struct {
	info Info
	Pool *pool.Pool
	partyIDs party.IDSlice
	otherPartyIDs party.IDSlice
	ssid []byte
	hash *hash.Hash
	mtx sync.Mutex
}
func NewSession(info Info, sessionID []byte, pl *pool.Pool, auxInfo ...hash.WriterToWithDomain) (*Helper, error) {
	partyIDs := party.NewIDSlice(info.PartyIDs)
	if !partyIDs.Valid() {
		return nil, errors.New("session: partyIDs invalid")
	}
	if !partyIDs.Contains(info.SelfID) {
		return nil, errors.New("session: selfID not included in partyIDs")
	}
	if info.Threshold < 0 || info.Threshold > math.MaxUint32 {
		return nil, fmt.Errorf("session: threshold %d is invalid", info.Threshold)
	}
	if n := len(partyIDs); n <= 0 || info.Threshold > n-1 {
		return nil, fmt.Errorf("session: threshold %d is invalid for number of parties %d", info.Threshold, n)
	}
	var err error
	h := hash.New()
	if sessionID != nil {
		if err = h.WriteAny(&hash.BytesWithDomain{
			TheDomain: "Session ID",
			Bytes:     sessionID,
		}); err != nil {
			return nil, fmt.Errorf("session: %w", err)
		}
	}
	if err = h.WriteAny(&hash.BytesWithDomain{
		TheDomain: "Protocol ID",
		Bytes:     []byte(info.ProtocolID),
	}); err != nil {
		return nil, fmt.Errorf("session: %w", err)
	}
	if info.Group != nil {
		if err = h.WriteAny(&hash.BytesWithDomain{
			TheDomain: "Group Name",
			Bytes:     []byte(info.Group.Name()),
		}); err != nil {
			return nil, fmt.Errorf("session: %w", err)
		}
	}
	if err = h.WriteAny(partyIDs); err != nil {
		return nil, fmt.Errorf("session: %w", err)
	}
	if err = h.WriteAny(types.ThresholdWrapper(info.Threshold)); err != nil {
		return nil, fmt.Errorf("session: %w", err)
	}
	for _, a := range auxInfo {
		if a == nil {
			continue
		}
		if err = h.WriteAny(a); err != nil {
			return nil, fmt.Errorf("session: %w", err)
		}
	}
	return &Helper{
		info:          info,
		Pool:          pl,
		partyIDs:      partyIDs,
		otherPartyIDs: partyIDs.Remove(info.SelfID),
		ssid:          h.Clone().Sum(),
		hash:          h,
	}, nil
}
func (h *Helper) HashForID(id party.ID) *hash.Hash {
	h.mtx.Lock()
	defer h.mtx.Unlock()
	cloned := h.hash.Clone()
	if id != "" {
		_ = cloned.WriteAny(id)
	}
	return cloned
}
func (h *Helper) UpdateHashState(value hash.WriterToWithDomain) {
	h.mtx.Lock()
	defer h.mtx.Unlock()
	_ = h.hash.WriteAny(value)
}