mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-12-26 00:25:17 +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
|
||
}
|