mirror of
https://github.com/luxfi/tss.git
synced 2026-10-30 15:14:51 +00:00
188 lines
5.6 KiB
Go
188 lines
5.6 KiB
Go
// Copyright © 2019 Binance
|
|
//
|
|
// This file is part of Binance. The full Binance copyright notice, including
|
|
// terms governing use, modification, and redistribution, is contained in the
|
|
// file LICENSE at the root of the source code distribution tree.
|
|
|
|
package resharing
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"math/big"
|
|
|
|
"github.com/luxfi/tss/v2/crypto/modproof"
|
|
|
|
"github.com/luxfi/tss/v2/crypto/dlnproof"
|
|
"github.com/luxfi/tss/v2/ecdsa/keygen"
|
|
"github.com/luxfi/tss/v2/tss"
|
|
)
|
|
|
|
var zero = big.NewInt(0)
|
|
|
|
func (round *round2) Start() *tss.Error {
|
|
if round.started {
|
|
return round.WrapError(errors.New("round already started"))
|
|
}
|
|
round.number = 2
|
|
round.started = true
|
|
round.resetOK() // resets both round.oldOK and round.newOK
|
|
round.allOldOK()
|
|
|
|
if !round.ReSharingParams().IsNewCommittee() {
|
|
return nil
|
|
}
|
|
|
|
Pi := round.PartyID()
|
|
i := Pi.Index
|
|
|
|
// check consistency of SSID
|
|
r1msg := round.temp.dgRound1Messages[0].Content().(*DGRound1Message)
|
|
SSID := r1msg.UnmarshalSSID()
|
|
for j, Pj := range round.OldParties().IDs() {
|
|
if j == 0 || j == i {
|
|
continue
|
|
}
|
|
r1msg := round.temp.dgRound1Messages[j].Content().(*DGRound1Message)
|
|
SSIDj := r1msg.UnmarshalSSID()
|
|
if !bytes.Equal(SSID, SSIDj) {
|
|
return round.WrapError(errors.New("ssid mismatch"), Pj)
|
|
}
|
|
}
|
|
round.temp.ssid = SSID
|
|
|
|
// 2. "broadcast" "ACK" members of the OLD committee
|
|
r2msg1 := NewDGRound2Message2(
|
|
round.OldParties().IDs().Exclude(round.PartyID()), round.PartyID())
|
|
round.temp.dgRound2Message2s[i] = r2msg1
|
|
round.out <- r2msg1
|
|
|
|
// 1.
|
|
// generate Paillier public key E_i, private key and proof
|
|
// generate safe primes for ZKPs later on
|
|
// compute ntilde, h1, h2 (uses safe primes)
|
|
// use the pre-params if they were provided to the LocalParty constructor
|
|
var preParams *keygen.LocalPreParams
|
|
if round.save.LocalPreParams.Validate() && !round.save.LocalPreParams.ValidateWithProof() {
|
|
return round.WrapError(
|
|
errors.New("`optionalPreParams` failed to validate; it might have been generated with an older version of tss-lib"))
|
|
} else if round.save.LocalPreParams.ValidateWithProof() {
|
|
preParams = &round.save.LocalPreParams
|
|
} else {
|
|
var err error
|
|
preParams, err = keygen.GeneratePreParams(round.SafePrimeGenTimeout(), round.Concurrency())
|
|
if err != nil {
|
|
return round.WrapError(errors.New("pre-params generation failed"), Pi)
|
|
}
|
|
}
|
|
round.save.LocalPreParams = *preParams
|
|
round.save.NTildej[i] = preParams.NTildei
|
|
round.save.H1j[i], round.save.H2j[i] = preParams.H1i, preParams.H2i
|
|
|
|
// generate the dlnproofs for resharing
|
|
h1i, h2i, alpha, beta, p, q, NTildei := preParams.H1i,
|
|
preParams.H2i,
|
|
preParams.Alpha,
|
|
preParams.Beta,
|
|
preParams.P,
|
|
preParams.Q,
|
|
preParams.NTildei
|
|
dlnProof1 := dlnproof.NewDLNProof(h1i, h2i, alpha, p, q, NTildei, round.Rand())
|
|
dlnProof2 := dlnproof.NewDLNProof(h2i, h1i, beta, p, q, NTildei, round.Rand())
|
|
|
|
modProof := &modproof.ProofMod{W: zero, X: *new([80]*big.Int), A: zero, B: zero, Z: *new([80]*big.Int)}
|
|
ContextI := append(round.temp.ssid, big.NewInt(int64(i)).Bytes()...)
|
|
if !round.Parameters.NoProofMod() {
|
|
var err error
|
|
modProof, err = modproof.NewProof(ContextI, preParams.PaillierSK.N, preParams.PaillierSK.P, preParams.PaillierSK.Q, round.Rand())
|
|
if err != nil {
|
|
return round.WrapError(err, Pi)
|
|
}
|
|
}
|
|
r2msg2, err := NewDGRound2Message1(
|
|
round.NewParties().IDs().Exclude(round.PartyID()), round.PartyID(),
|
|
&preParams.PaillierSK.PublicKey, modProof, preParams.NTildei, preParams.H1i, preParams.H2i, dlnProof1, dlnProof2)
|
|
if err != nil {
|
|
return round.WrapError(err, Pi)
|
|
}
|
|
round.temp.dgRound2Message1s[i] = r2msg2
|
|
round.out <- r2msg2
|
|
|
|
// for this P: SAVE de-commitments, paillier keys for round 2
|
|
round.save.PaillierSK = preParams.PaillierSK
|
|
round.save.PaillierPKs[i] = &preParams.PaillierSK.PublicKey
|
|
round.save.NTildej[i] = preParams.NTildei
|
|
round.save.H1j[i], round.save.H2j[i] = preParams.H1i, preParams.H2i
|
|
|
|
return nil
|
|
}
|
|
|
|
func (round *round2) CanAccept(msg tss.ParsedMessage) bool {
|
|
if round.ReSharingParams().IsNewCommittee() {
|
|
if _, ok := msg.Content().(*DGRound2Message1); ok {
|
|
return msg.IsBroadcast()
|
|
}
|
|
}
|
|
if round.ReSharingParams().IsOldCommittee() {
|
|
if _, ok := msg.Content().(*DGRound2Message2); ok {
|
|
return msg.IsBroadcast()
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (round *round2) Update() (bool, *tss.Error) {
|
|
ret := true
|
|
if round.ReSharingParams().IsOldCommittee() && round.ReSharingParameters.IsNewCommittee() {
|
|
// accept messages from new -> old committee
|
|
for j, msg1 := range round.temp.dgRound2Message2s {
|
|
if round.newOK[j] {
|
|
continue
|
|
}
|
|
if msg1 == nil || !round.CanAccept(msg1) {
|
|
ret = false
|
|
continue
|
|
}
|
|
// accept message from new -> committee
|
|
msg2 := round.temp.dgRound2Message1s[j]
|
|
if msg2 == nil || !round.CanAccept(msg2) {
|
|
ret = false
|
|
continue
|
|
}
|
|
round.newOK[j] = true
|
|
}
|
|
} else if round.ReSharingParams().IsOldCommittee() {
|
|
// accept messages from new -> old committee
|
|
for j, msg := range round.temp.dgRound2Message2s {
|
|
if round.newOK[j] {
|
|
continue
|
|
}
|
|
if msg == nil || !round.CanAccept(msg) {
|
|
ret = false
|
|
continue
|
|
}
|
|
round.newOK[j] = true
|
|
}
|
|
} else if round.ReSharingParams().IsNewCommittee() {
|
|
// accept messages from new -> new committee
|
|
for j, msg := range round.temp.dgRound2Message1s {
|
|
if round.newOK[j] {
|
|
continue
|
|
}
|
|
if msg == nil || !round.CanAccept(msg) {
|
|
ret = false
|
|
continue
|
|
}
|
|
round.newOK[j] = true
|
|
}
|
|
} else {
|
|
return false, round.WrapError(errors.New("this party is not in the old or the new committee"), round.PartyID())
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
func (round *round2) NextRound() tss.Round {
|
|
round.started = false
|
|
return &round3{round}
|
|
}
|