github.com/annchain/OG@v0.0.9/consensus/dkg/dkg_context.go (about)

     1  // Copyright © 2019 Annchain Authors <EMAIL ADDRESS>
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  package dkg
    15  
    16  import (
    17  	"errors"
    18  	"github.com/annchain/kyber/v3"
    19  	"github.com/annchain/kyber/v3/pairing/bn256"
    20  	"github.com/annchain/kyber/v3/share"
    21  	"github.com/annchain/kyber/v3/share/dkg/pedersen"
    22  	"github.com/annchain/kyber/v3/sign/bls"
    23  	"github.com/annchain/kyber/v3/sign/tbls"
    24  )
    25  
    26  // DkgContext stores the DKG info collected from other peers.
    27  // It can sign messages individually and recover the joint sig once enough peers share their partSigs
    28  // It is the core algorithm of DKG
    29  type DkgContext struct {
    30  	SessionId uint32
    31  	MyIndex   uint32
    32  	Me        PartSec
    33  	PartPubs  []PartPub // must be ordered from the outside
    34  
    35  	//CandidatePartSec      []kyber.Scalar
    36  	//CandidatePublicKey    [][]byte
    37  	//addressIndex          map[common.Address]int
    38  	//SecretKeyContribution map[common.Address]kyber.Scalar
    39  	Suite *bn256.Suite
    40  	Dkger *dkg.DistKeyGenerator // backend algorithm
    41  	//Resps                 map[common.Address]*dkg.Response
    42  	//dealsIndex            map[uint32]bool
    43  	Threshold      int
    44  	NbParticipants int
    45  	JointPubKey    kyber.Point
    46  	//responseNumber        int
    47  	//SigShares [][]byte
    48  	KeyShare *dkg.DistKeyShare // cache of the DistKeyShare to avoid recovery multiple times
    49  }
    50  
    51  func NewDkgContext(s *bn256.Suite, termId uint32) *DkgContext {
    52  	c := &DkgContext{
    53  		Suite: s,
    54  		//addressIndex:          make(map[common.Address]int),
    55  		//SecretKeyContribution: make(map[common.Address]kyber.Scalar),
    56  		//Resps:                 make(map[common.Address]*dkg.Response),
    57  		SessionId: termId,
    58  		//dealsIndex:            make(map[uint32]bool),
    59  	}
    60  	return c
    61  }
    62  
    63  // GenerateDKGer inits a dkg by all part-public keys and my part-private key
    64  // Then it is possible to sign and verify data.
    65  func (p *DkgContext) GenerateDKGer() error {
    66  	// use all partPubs and my partSec to generate a dkg
    67  	log.WithField("partPubLen", len(p.PartPubs)).Debug("generating DKGer")
    68  	participants := PartPubs(p.PartPubs).Points()
    69  	dkger, err := dkg.NewDistKeyGenerator(p.Suite, p.Me.Scalar, participants, p.Threshold)
    70  	if err != nil {
    71  		log.WithField("dkger", dkger).WithError(err).Error("generate dkg error")
    72  		return err
    73  	}
    74  	p.Dkger = dkger
    75  	p.KeyShare = nil
    76  	return nil
    77  }
    78  
    79  func (p *DkgContext) ensureKeyShare() (err error) {
    80  	dks := p.KeyShare
    81  	if dks == nil {
    82  		dks, err = p.Dkger.DistKeyShare()
    83  		if err != nil {
    84  			return
    85  		}
    86  		p.KeyShare = dks
    87  	}
    88  	return nil
    89  }
    90  
    91  // VerifyByPubPoly verifies signature for msg
    92  func (p *DkgContext) VerifyByPubPoly(msg []byte, sig []byte) (err error) {
    93  	if err = p.ensureKeyShare(); err != nil {
    94  		return
    95  	}
    96  	pubPoly := share.NewPubPoly(p.Suite, p.Suite.Point().Base(), p.KeyShare.Commitments())
    97  
    98  	//TODO: remove these check. It is only for debugging
    99  	if pubPoly.Commit() != p.KeyShare.Public() {
   100  		err = errors.New("PubPoly not aligned to dksPublic")
   101  		return
   102  	}
   103  
   104  	err = bls.Verify(p.Suite, pubPoly.Commit(), msg, sig)
   105  	log.Tracef(" pubPolyCommit [%s] dksPublic [%s] dksCommitments [%s]\n",
   106  		pubPoly.Commit(), p.KeyShare.Public(), p.KeyShare.Commitments())
   107  	return
   108  }
   109  
   110  // VerifyByDksPublic verifies signature for msg
   111  func (p *DkgContext) VerifyByDksPublic(msg []byte, sig []byte) (err error) {
   112  	if err = p.ensureKeyShare(); err != nil {
   113  		return
   114  	}
   115  	err = bls.Verify(p.Suite, p.KeyShare.Public(), msg, sig)
   116  	return
   117  }
   118  
   119  // RecoverSig builds a jointSignature from sigShares collected from enough participants
   120  func (p *DkgContext) RecoverSig(msg []byte, sigShares [][]byte) (jointSig []byte, err error) {
   121  	if err = p.ensureKeyShare(); err != nil {
   122  		return
   123  	}
   124  	pubPoly := share.NewPubPoly(p.Suite, p.Suite.Point().Base(), p.KeyShare.Commitments())
   125  	jointSig, err = tbls.Recover(p.Suite, pubPoly, msg, sigShares, p.Threshold, p.NbParticipants)
   126  	return
   127  }
   128  
   129  // RecoverPub builds a joint public key from keyshares collected from all other participants
   130  func (p *DkgContext) RecoverPub() (jointPubKey kyber.Point, err error) {
   131  	if err = p.ensureKeyShare(); err != nil {
   132  		return
   133  	}
   134  	pubPoly := share.NewPubPoly(p.Suite, p.Suite.Point().Base(), p.KeyShare.Commitments())
   135  	jointPubKey = pubPoly.Commit()
   136  	p.JointPubKey = jointPubKey
   137  	return
   138  }
   139  
   140  // PartSig signs the message into a single sigShare.
   141  func (p *DkgContext) PartSig(msg []byte) (partSig []byte, err error) {
   142  	if err = p.ensureKeyShare(); err != nil {
   143  		return
   144  	}
   145  	partSig, err = tbls.Sign(p.Suite, p.KeyShare.PriShare(), msg)
   146  	return
   147  }