mirror of
				https://source.quilibrium.com/quilibrium/ceremonyclient.git
				synced 2025-11-03 23:57:26 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			81 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			81 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
//
 | 
						||
// Copyright Coinbase, Inc. All Rights Reserved.
 | 
						||
//
 | 
						||
// SPDX-License-Identifier: Apache-2.0
 | 
						||
//
 | 
						||
 | 
						||
package gennaro
 | 
						||
 | 
						||
import (
 | 
						||
	"fmt"
 | 
						||
	"math/big"
 | 
						||
 | 
						||
	"source.quilibrium.com/quilibrium/monorepo/nekryptology/internal"
 | 
						||
	"source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/core"
 | 
						||
	v1 "source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/sharing/v1"
 | 
						||
)
 | 
						||
 | 
						||
// Round1Bcast are the values that are broadcast to all other participants
 | 
						||
// after round1 completes
 | 
						||
type Round1Bcast = []*v1.ShareVerifier
 | 
						||
 | 
						||
// Round1P2PSend are the values that are sent to individual participants based
 | 
						||
// on the id
 | 
						||
type Round1P2PSend = map[uint32]*Round1P2PSendPacket
 | 
						||
 | 
						||
// Round1P2PSendPacket are the shares generated from the secret for a specific participant
 | 
						||
type Round1P2PSendPacket struct {
 | 
						||
	SecretShare   *v1.ShamirShare
 | 
						||
	BlindingShare *v1.ShamirShare
 | 
						||
}
 | 
						||
 | 
						||
// Round1 computes the first round for the DKG
 | 
						||
// `secret` can be nil
 | 
						||
// NOTE: if `secret` is nil, a new secret is generated which creates a new key
 | 
						||
// if `secret` is set, then this performs key resharing aka proactive secret sharing update
 | 
						||
func (dp *Participant) Round1(secret []byte) (Round1Bcast, Round1P2PSend, error) {
 | 
						||
	if dp.round != 1 {
 | 
						||
		return nil, nil, internal.ErrInvalidRound
 | 
						||
	}
 | 
						||
 | 
						||
	if secret == nil {
 | 
						||
		// 1. x $← Zq∗
 | 
						||
		s, err := dp.scalar.Random()
 | 
						||
		if err != nil {
 | 
						||
			return nil, nil, err
 | 
						||
		}
 | 
						||
		secret = s.Bytes()
 | 
						||
	} else {
 | 
						||
		s := new(big.Int).SetBytes(secret)
 | 
						||
		if !dp.scalar.IsValid(s) {
 | 
						||
			return nil, nil, fmt.Errorf("invalid secret value")
 | 
						||
		}
 | 
						||
		if s.Cmp(core.Zero) == 0 {
 | 
						||
			return nil, nil, internal.ErrZeroValue
 | 
						||
		}
 | 
						||
	}
 | 
						||
 | 
						||
	var err error
 | 
						||
	// 2. {X1,...,Xt},{R1,...,Rt},{x1,...,xn},{r1,...,rn}= PedersenFeldmanShare(E,Q,x,t,{p1,...,pn})
 | 
						||
	dp.pedersenResult, err = dp.pedersen.Split(secret)
 | 
						||
 | 
						||
	if err != nil {
 | 
						||
		return nil, nil, err
 | 
						||
	}
 | 
						||
 | 
						||
	// 4. P2PSend x_j,r_j to participant p_j in {p_1,...,p_n}_{i != j}
 | 
						||
	p2pSend := make(Round1P2PSend, len(dp.otherParticipantShares))
 | 
						||
	for id := range dp.otherParticipantShares {
 | 
						||
		p2pSend[id] = &Round1P2PSendPacket{
 | 
						||
			SecretShare:   dp.pedersenResult.SecretShares[id-1],
 | 
						||
			BlindingShare: dp.pedersenResult.BlindingShares[id-1],
 | 
						||
		}
 | 
						||
	}
 | 
						||
 | 
						||
	// Update internal state
 | 
						||
	dp.round = 2
 | 
						||
 | 
						||
	// 3. EchoBroadcast {X_1,...,X_t} to all other participants.
 | 
						||
	return dp.pedersenResult.BlindedVerifiers, p2pSend, nil
 | 
						||
}
 |