aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJimmy Hu <jimmy.hu@dexon.org>2019-03-12 11:39:23 +0800
committerGitHub <noreply@github.com>2019-03-12 11:39:23 +0800
commitd111602d77a06d16a3206247a15895779720cfcf (patch)
tree189cd0fd73167f2c9fb20db0821c6eb16b999eb8
parentc3bda77db1c2620c5212d4369792b923227d2570 (diff)
downloaddexon-consensus-d111602d77a06d16a3206247a15895779720cfcf.tar
dexon-consensus-d111602d77a06d16a3206247a15895779720cfcf.tar.gz
dexon-consensus-d111602d77a06d16a3206247a15895779720cfcf.tar.bz2
dexon-consensus-d111602d77a06d16a3206247a15895779720cfcf.tar.lz
dexon-consensus-d111602d77a06d16a3206247a15895779720cfcf.tar.xz
dexon-consensus-d111602d77a06d16a3206247a15895779720cfcf.tar.zst
dexon-consensus-d111602d77a06d16a3206247a15895779720cfcf.zip
core: split GroupPublicKey and NodePublicKeys (#484)
* core: add benchmark * core: split NPKs and GPK * Add benchmark
-rw-r--r--core/configuration-chain.go48
-rw-r--r--core/configuration-chain_test.go28
-rw-r--r--core/dkg-tsig-protocol.go18
-rw-r--r--core/dkg-tsig-protocol_test.go99
-rw-r--r--core/types/dkg/dkg.go101
5 files changed, 220 insertions, 74 deletions
diff --git a/core/configuration-chain.go b/core/configuration-chain.go
index ecca43c..9e8df6b 100644
--- a/core/configuration-chain.go
+++ b/core/configuration-chain.go
@@ -48,7 +48,7 @@ type configurationChain struct {
logger common.Logger
dkgLock sync.RWMutex
dkgSigner map[uint64]*dkgShareSecret
- gpk map[uint64]*typesDKG.GroupPublicKey
+ npks map[uint64]*typesDKG.NodePublicKeys
dkgResult sync.RWMutex
tsig map[common.Hash]*tsigProtocol
tsigTouched map[common.Hash]struct{}
@@ -76,7 +76,7 @@ func newConfigurationChain(
gov: gov,
logger: logger,
dkgSigner: make(map[uint64]*dkgShareSecret),
- gpk: make(map[uint64]*typesDKG.GroupPublicKey),
+ npks: make(map[uint64]*typesDKG.NodePublicKeys),
tsig: make(map[common.Hash]*tsigProtocol),
tsigTouched: make(map[common.Hash]struct{}),
tsigReady: sync.NewCond(&sync.Mutex{}),
@@ -221,7 +221,7 @@ func (cc *configurationChain) runDKG(round uint64) error {
}
cc.logger.Debug("Calling Governance.DKGMasterPublicKeys", "round", round)
cc.logger.Debug("Calling Governance.DKGComplaints", "round", round)
- gpk, err := typesDKG.NewGroupPublicKey(round,
+ npks, err := typesDKG.NewNodePublicKeys(round,
cc.gov.DKGMasterPublicKeys(round),
cc.gov.DKGComplaints(round),
cc.dkg.threshold)
@@ -229,19 +229,19 @@ func (cc *configurationChain) runDKG(round uint64) error {
return err
}
qualifies := ""
- for nID := range gpk.QualifyNodeIDs {
+ for nID := range npks.QualifyNodeIDs {
qualifies += fmt.Sprintf("%s ", nID.String()[:6])
}
cc.logger.Info("Qualify Nodes",
"nodeID", cc.ID,
"round", round,
- "count", len(gpk.QualifyIDs),
+ "count", len(npks.QualifyIDs),
"qualifies", qualifies)
- if _, exist := gpk.QualifyNodeIDs[cc.ID]; !exist {
+ if _, exist := npks.QualifyNodeIDs[cc.ID]; !exist {
cc.logger.Warn("Self is not in Qualify Nodes")
return nil
}
- signer, err := cc.dkg.recoverShareSecret(gpk.QualifyIDs)
+ signer, err := cc.dkg.recoverShareSecret(npks.QualifyIDs)
if err != nil {
return err
}
@@ -252,7 +252,7 @@ func (cc *configurationChain) runDKG(round uint64) error {
cc.dkgResult.Lock()
defer cc.dkgResult.Unlock()
cc.dkgSigner[round] = signer
- cc.gpk[round] = gpk
+ cc.npks[round] = npks
return nil
}
@@ -265,40 +265,40 @@ func (cc *configurationChain) isDKGFinal(round uint64) bool {
}
func (cc *configurationChain) getDKGInfo(
- round uint64) (*typesDKG.GroupPublicKey, *dkgShareSecret, error) {
- getFromCache := func() (*typesDKG.GroupPublicKey, *dkgShareSecret) {
+ round uint64) (*typesDKG.NodePublicKeys, *dkgShareSecret, error) {
+ getFromCache := func() (*typesDKG.NodePublicKeys, *dkgShareSecret) {
cc.dkgResult.RLock()
defer cc.dkgResult.RUnlock()
- gpk := cc.gpk[round]
+ npks := cc.npks[round]
signer := cc.dkgSigner[round]
- return gpk, signer
+ return npks, signer
}
- gpk, signer := getFromCache()
- if gpk == nil || signer == nil {
+ npks, signer := getFromCache()
+ if npks == nil || signer == nil {
if err := cc.recoverDKGInfo(round); err != nil {
return nil, nil, err
}
- gpk, signer = getFromCache()
+ npks, signer = getFromCache()
}
- if gpk == nil || signer == nil {
+ if npks == nil || signer == nil {
return nil, nil, ErrDKGNotReady
}
- return gpk, signer, nil
+ return npks, signer, nil
}
func (cc *configurationChain) recoverDKGInfo(round uint64) error {
cc.dkgResult.Lock()
defer cc.dkgResult.Unlock()
_, signerExists := cc.dkgSigner[round]
- _, gpkExists := cc.gpk[round]
- if signerExists && gpkExists {
+ _, npksExists := cc.npks[round]
+ if signerExists && npksExists {
return nil
}
if !cc.gov.IsDKGFinal(round) {
return ErrDKGNotReady
}
// Restore group public key.
- gpk, err := typesDKG.NewGroupPublicKey(round,
+ npks, err := typesDKG.NewNodePublicKeys(round,
cc.gov.DKGMasterPublicKeys(round),
cc.gov.DKGComplaints(round),
utils.GetDKGThreshold(
@@ -311,7 +311,7 @@ func (cc *configurationChain) recoverDKGInfo(round uint64) error {
if err != nil {
return err
}
- cc.gpk[round] = gpk
+ cc.npks[round] = npks
cc.dkgSigner[round] = &dkgShareSecret{
privateKey: &prvKey,
}
@@ -349,8 +349,8 @@ func (cc *configurationChain) untouchTSigHash(hash common.Hash) {
func (cc *configurationChain) runTSig(
round uint64, hash common.Hash) (
crypto.Signature, error) {
- gpk, _, _ := cc.getDKGInfo(round)
- if gpk == nil {
+ npks, _, _ := cc.getDKGInfo(round)
+ if npks == nil {
return crypto.Signature{}, ErrDKGNotReady
}
cc.tsigReady.L.Lock()
@@ -358,7 +358,7 @@ func (cc *configurationChain) runTSig(
if _, exist := cc.tsig[hash]; exist {
return crypto.Signature{}, ErrTSigAlreadyRunning
}
- cc.tsig[hash] = newTSigProtocol(gpk, hash)
+ cc.tsig[hash] = newTSigProtocol(npks, hash)
pendingPsig := cc.pendingPsig[hash]
delete(cc.pendingPsig, hash)
go func() {
diff --git a/core/configuration-chain_test.go b/core/configuration-chain_test.go
index f7a81da..fd7e6a3 100644
--- a/core/configuration-chain_test.go
+++ b/core/configuration-chain_test.go
@@ -247,10 +247,10 @@ func (s *ConfigurationChainTestSuite) preparePartialSignature(
psigs []*typesDKG.PartialSignature) {
psigs = make([]*typesDKG.PartialSignature, 0, len(cfgChains))
for nID, cc := range cfgChains {
- if _, exist := cc.gpk[round]; !exist {
+ if _, exist := cc.npks[round]; !exist {
continue
}
- if _, exist := cc.gpk[round].QualifyNodeIDs[nID]; !exist {
+ if _, exist := cc.npks[round].QualifyNodeIDs[nID]; !exist {
continue
}
psig, err := cc.preparePartialSignature(round, hash)
@@ -281,10 +281,10 @@ func (s *ConfigurationChainTestSuite) TestConfigurationChain() {
errs := make(chan error, n)
tsigChan := make(chan crypto.Signature, n)
for nID, cc := range cfgChains {
- if _, exist := cc.gpk[round]; !exist {
+ if _, exist := cc.npks[round]; !exist {
continue
}
- if _, exist := cc.gpk[round].QualifyNodeIDs[nID]; !exist {
+ if _, exist := cc.npks[round].QualifyNodeIDs[nID]; !exist {
continue
}
go func(cc *configurationChain) {
@@ -299,10 +299,10 @@ func (s *ConfigurationChainTestSuite) TestConfigurationChain() {
}
}
for nID, cc := range cfgChains {
- if _, exist := cc.gpk[round]; !exist {
+ if _, exist := cc.npks[round]; !exist {
s.FailNow("Should be qualifyied")
}
- if _, exist := cc.gpk[round].QualifyNodeIDs[nID]; !exist {
+ if _, exist := cc.npks[round].QualifyNodeIDs[nID]; !exist {
s.FailNow("Should be qualifyied")
}
s.Require().NoError(<-errs)
@@ -369,12 +369,12 @@ func (s *ConfigurationChainTestSuite) TestDKGMasterPublicKeyDelayAdd() {
}
for nID, cc := range cfgChains {
shouldExist := nID != delayNode
- _, exist := cc.gpk[round]
+ _, exist := cc.npks[round]
s.Equal(shouldExist, exist)
if !exist {
continue
}
- _, exist = cc.gpk[round].QualifyNodeIDs[nID]
+ _, exist = cc.npks[round].QualifyNodeIDs[nID]
s.Equal(shouldExist, exist)
}
}
@@ -446,10 +446,10 @@ func (s *ConfigurationChainTestSuite) TestDKGComplaintDelayAdd() {
s.Require().NoError(<-errs)
}
for nID, cc := range cfgChains {
- if _, exist := cc.gpk[round]; !exist {
+ if _, exist := cc.npks[round]; !exist {
s.FailNow("Should be qualifyied")
}
- if _, exist := cc.gpk[round].QualifyNodeIDs[nID]; !exist {
+ if _, exist := cc.npks[round].QualifyNodeIDs[nID]; !exist {
s.FailNow("Should be qualifyied")
}
}
@@ -474,7 +474,7 @@ func (s *ConfigurationChainTestSuite) TestMultipleTSig() {
tsigChan1 := make(chan crypto.Signature, n)
tsigChan2 := make(chan crypto.Signature, n)
for nID, cc := range cfgChains {
- if _, exist := cc.gpk[round].QualifyNodeIDs[nID]; !exist {
+ if _, exist := cc.npks[round].QualifyNodeIDs[nID]; !exist {
continue
}
go func(cc *configurationChain) {
@@ -499,7 +499,7 @@ func (s *ConfigurationChainTestSuite) TestMultipleTSig() {
}
}
for nID, cc := range cfgChains {
- if _, exist := cc.gpk[round].QualifyNodeIDs[nID]; !exist {
+ if _, exist := cc.npks[round].QualifyNodeIDs[nID]; !exist {
continue
}
s.Require().NoError(<-errs)
@@ -529,7 +529,7 @@ func (s *ConfigurationChainTestSuite) TestTSigTimeout() {
errs := make(chan error, n)
qualify := 0
for nID, cc := range cfgChains {
- if _, exist := cc.gpk[round].QualifyNodeIDs[nID]; !exist {
+ if _, exist := cc.npks[round].QualifyNodeIDs[nID]; !exist {
continue
}
qualify++
@@ -545,7 +545,7 @@ func (s *ConfigurationChainTestSuite) TestTSigTimeout() {
time.Sleep(timeout)
s.Require().Len(errs, qualify)
for nID, cc := range cfgChains {
- if _, exist := cc.gpk[round].QualifyNodeIDs[nID]; !exist {
+ if _, exist := cc.npks[round].QualifyNodeIDs[nID]; !exist {
continue
}
s.Equal(<-errs, ErrNotEnoughtPartialSignatures)
diff --git a/core/dkg-tsig-protocol.go b/core/dkg-tsig-protocol.go
index 46e975a..6c812db 100644
--- a/core/dkg-tsig-protocol.go
+++ b/core/dkg-tsig-protocol.go
@@ -129,7 +129,7 @@ type TSigVerifierCache struct {
}
type tsigProtocol struct {
- groupPublicKey *typesDKG.GroupPublicKey
+ nodePublicKeys *typesDKG.NodePublicKeys
hash common.Hash
sigs map[dkg.ID]dkg.PartialSignature
threshold int
@@ -464,17 +464,17 @@ func (tc *TSigVerifierCache) Get(round uint64) (TSigVerifier, bool) {
}
func newTSigProtocol(
- gpk *typesDKG.GroupPublicKey,
+ npks *typesDKG.NodePublicKeys,
hash common.Hash) *tsigProtocol {
return &tsigProtocol{
- groupPublicKey: gpk,
+ nodePublicKeys: npks,
hash: hash,
- sigs: make(map[dkg.ID]dkg.PartialSignature, gpk.Threshold+1),
+ sigs: make(map[dkg.ID]dkg.PartialSignature, npks.Threshold+1),
}
}
func (tsig *tsigProtocol) sanityCheck(psig *typesDKG.PartialSignature) error {
- _, exist := tsig.groupPublicKey.PublicKeys[psig.ProposerID]
+ _, exist := tsig.nodePublicKeys.PublicKeys[psig.ProposerID]
if !exist {
return ErrNotQualifyDKGParticipant
}
@@ -493,17 +493,17 @@ func (tsig *tsigProtocol) sanityCheck(psig *typesDKG.PartialSignature) error {
func (tsig *tsigProtocol) processPartialSignature(
psig *typesDKG.PartialSignature) error {
- if psig.Round != tsig.groupPublicKey.Round {
+ if psig.Round != tsig.nodePublicKeys.Round {
return nil
}
- id, exist := tsig.groupPublicKey.IDMap[psig.ProposerID]
+ id, exist := tsig.nodePublicKeys.IDMap[psig.ProposerID]
if !exist {
return ErrNotQualifyDKGParticipant
}
if err := tsig.sanityCheck(psig); err != nil {
return err
}
- pubKey := tsig.groupPublicKey.PublicKeys[psig.ProposerID]
+ pubKey := tsig.nodePublicKeys.PublicKeys[psig.ProposerID]
if !pubKey.VerifySignature(
tsig.hash, crypto.Signature(psig.PartialSignature)) {
return ErrIncorrectPartialSignature
@@ -513,7 +513,7 @@ func (tsig *tsigProtocol) processPartialSignature(
}
func (tsig *tsigProtocol) signature() (crypto.Signature, error) {
- if len(tsig.sigs) < tsig.groupPublicKey.Threshold {
+ if len(tsig.sigs) < tsig.nodePublicKeys.Threshold {
return crypto.Signature{}, ErrNotEnoughtPartialSignatures
}
ids := make(dkg.IDs, 0, len(tsig.sigs))
diff --git a/core/dkg-tsig-protocol_test.go b/core/dkg-tsig-protocol_test.go
index 88f78d3..88d1443 100644
--- a/core/dkg-tsig-protocol_test.go
+++ b/core/dkg-tsig-protocol_test.go
@@ -204,8 +204,7 @@ func (s *DKGTSIGProtocolTestSuite) TestDKGTSIGProtocol() {
// DKG is fininished.
gpk, err := typesDKG.NewGroupPublicKey(round,
gov.DKGMasterPublicKeys(round), gov.DKGComplaints(round),
- k,
- )
+ k)
s.Require().NoError(err)
s.Require().Len(gpk.QualifyIDs, n)
qualifyIDs := make(map[dkg.ID]struct{}, len(gpk.QualifyIDs))
@@ -231,8 +230,11 @@ func (s *DKGTSIGProtocolTestSuite) TestDKGTSIGProtocol() {
s.Require().NoError(err)
}
+ npks, err := typesDKG.NewNodePublicKeys(round,
+ gov.DKGMasterPublicKeys(round), gov.DKGComplaints(round), k)
+ s.Require().NoError(err)
msgHash := crypto.Keccak256Hash([]byte("🏖🍹"))
- tsig := newTSigProtocol(gpk, msgHash)
+ tsig := newTSigProtocol(npks, msgHash)
for nID, shareSecret := range shareSecrets {
psig := &typesDKG.PartialSignature{
ProposerID: nID,
@@ -788,7 +790,10 @@ func (s *DKGTSIGProtocolTestSuite) TestPartialSignature() {
}
msgHash := crypto.Keccak256Hash([]byte("🏖🍹"))
- tsig := newTSigProtocol(gpk, msgHash)
+ npks, err := typesDKG.NewNodePublicKeys(round,
+ gov.DKGMasterPublicKeys(round), gov.DKGComplaints(round), k)
+ s.Require().NoError(err)
+ tsig := newTSigProtocol(npks, msgHash)
byzantineID2 := s.nIDs[1]
byzantineID3 := s.nIDs[2]
for nID, shareSecret := range shareSecrets {
@@ -937,3 +942,89 @@ func (s *DKGTSIGProtocolTestSuite) TestTSigVerifierCache() {
func TestDKGTSIGProtocol(t *testing.T) {
suite.Run(t, new(DKGTSIGProtocolTestSuite))
}
+
+func BenchmarkGPK4_7(b *testing.B) { benchmarkDKGGroupPubliKey(4, 7, b) }
+func BenchmarkGPK9_13(b *testing.B) { benchmarkDKGGroupPubliKey(9, 13, b) }
+func BenchmarkGPK17_24(b *testing.B) { benchmarkDKGGroupPubliKey(17, 24, b) }
+func BenchmarkGPK81_121(b *testing.B) { benchmarkDKGGroupPubliKey(81, 121, b) }
+
+func benchmarkDKGGroupPubliKey(k, n int, b *testing.B) {
+ round := uint64(1)
+ _, pubKeys, err := test.NewKeys(n)
+ if err != nil {
+ panic(err)
+ }
+ gov, err := test.NewGovernance(test.NewState(DKGDelayRound,
+ pubKeys, 100, &common.NullLogger{}, true), ConfigRoundShift)
+ if err != nil {
+ panic(err)
+ }
+
+ for _, pk := range pubKeys {
+ _, pubShare := dkg.NewPrivateKeyShares(k)
+ gov.AddDKGMasterPublicKey(round, &typesDKG.MasterPublicKey{
+ ProposerID: types.NewNodeID(pk),
+ Round: round,
+ DKGID: typesDKG.NewID(types.NewNodeID(pk)),
+ PublicKeyShares: *pubShare,
+ })
+ }
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ // DKG is fininished.
+ gpk, err := typesDKG.NewGroupPublicKey(round,
+ gov.DKGMasterPublicKeys(round), gov.DKGComplaints(round),
+ k,
+ )
+ if err != nil {
+ panic(err)
+ }
+ if len(gpk.QualifyIDs) != n {
+ panic("not enough of qualify id")
+ }
+ }
+}
+
+func BenchmarkNPKs4_7(b *testing.B) { benchmarkDKGNodePubliKeys(4, 7, b) }
+func BenchmarkNPKs9_13(b *testing.B) { benchmarkDKGNodePubliKeys(9, 13, b) }
+func BenchmarkNPKs17_24(b *testing.B) { benchmarkDKGNodePubliKeys(17, 24, b) }
+func BenchmarkNPKs81_121(b *testing.B) { benchmarkDKGNodePubliKeys(81, 121, b) }
+
+func benchmarkDKGNodePubliKeys(k, n int, b *testing.B) {
+ round := uint64(1)
+ _, pubKeys, err := test.NewKeys(n)
+ if err != nil {
+ panic(err)
+ }
+ gov, err := test.NewGovernance(test.NewState(DKGDelayRound,
+ pubKeys, 100, &common.NullLogger{}, true), ConfigRoundShift)
+ if err != nil {
+ panic(err)
+ }
+
+ for _, pk := range pubKeys {
+ _, pubShare := dkg.NewPrivateKeyShares(k)
+ gov.AddDKGMasterPublicKey(round, &typesDKG.MasterPublicKey{
+ ProposerID: types.NewNodeID(pk),
+ Round: round,
+ DKGID: typesDKG.NewID(types.NewNodeID(pk)),
+ PublicKeyShares: *pubShare,
+ })
+ }
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ // DKG is fininished.
+ npks, err := typesDKG.NewNodePublicKeys(round,
+ gov.DKGMasterPublicKeys(round), gov.DKGComplaints(round),
+ k,
+ )
+ if err != nil {
+ panic(err)
+ }
+ if len(npks.QualifyIDs) != n {
+ panic("not enough of qualify id")
+ }
+ }
+}
diff --git a/core/types/dkg/dkg.go b/core/types/dkg/dkg.go
index 00c04be..1052ccb 100644
--- a/core/types/dkg/dkg.go
+++ b/core/types/dkg/dkg.go
@@ -289,7 +289,6 @@ type GroupPublicKey struct {
QualifyIDs cryptoDKG.IDs
QualifyNodeIDs map[types.NodeID]struct{}
IDMap map[types.NodeID]cryptoDKG.ID
- PublicKeys map[types.NodeID]*cryptoDKG.PublicKey
GroupPublicKey *cryptoDKG.PublicKey
Threshold int
}
@@ -300,15 +299,12 @@ func (gpk *GroupPublicKey) VerifySignature(
return gpk.GroupPublicKey.VerifySignature(hash, sig)
}
-// NewGroupPublicKey creats a GroupPublicKey instance.
-func NewGroupPublicKey(
- round uint64,
- mpks []*MasterPublicKey, complaints []*Complaint,
- threshold int) (
- *GroupPublicKey, error) {
-
+func calcQualifyNodes(
+ mpks []*MasterPublicKey, complaints []*Complaint, threshold int) (
+ qualifyIDs cryptoDKG.IDs, qualifyNodeIDs map[types.NodeID]struct{}, err error) {
if len(mpks) < threshold {
- return nil, ErrInvalidThreshold
+ err = ErrInvalidThreshold
+ return
}
// Calculate qualify members.
@@ -331,21 +327,87 @@ func NewGroupPublicKey(
disqualifyIDs[nID] = struct{}{}
}
}
- qualifyIDs := make(cryptoDKG.IDs, 0, len(mpks)-len(disqualifyIDs))
+ qualifyIDs = make(cryptoDKG.IDs, 0, len(mpks)-len(disqualifyIDs))
if cap(qualifyIDs) < threshold {
- return nil, ErrNotReachThreshold
+ err = ErrNotReachThreshold
+ return
+ }
+ qualifyNodeIDs = make(map[types.NodeID]struct{})
+ for _, mpk := range mpks {
+ if _, exist := disqualifyIDs[mpk.ProposerID]; exist {
+ continue
+ }
+ qualifyIDs = append(qualifyIDs, mpk.DKGID)
+ qualifyNodeIDs[mpk.ProposerID] = struct{}{}
+ }
+ return
+}
+
+// NewGroupPublicKey creats a GroupPublicKey instance.
+func NewGroupPublicKey(
+ round uint64,
+ mpks []*MasterPublicKey, complaints []*Complaint,
+ threshold int) (
+ *GroupPublicKey, error) {
+ qualifyIDs, qualifyNodeIDs, err :=
+ calcQualifyNodes(mpks, complaints, threshold)
+ if err != nil {
+ return nil, err
}
- qualifyNodeIDs := make(map[types.NodeID]struct{})
mpkMap := make(map[cryptoDKG.ID]*MasterPublicKey, cap(qualifyIDs))
idMap := make(map[types.NodeID]cryptoDKG.ID)
for _, mpk := range mpks {
- if _, exist := disqualifyIDs[mpk.ProposerID]; exist {
+ if _, exist := qualifyNodeIDs[mpk.ProposerID]; !exist {
+ continue
+ }
+ mpkMap[mpk.DKGID] = mpk
+ idMap[mpk.ProposerID] = mpk.DKGID
+ }
+ // Recover Group Public Key.
+ pubShares := make([]*cryptoDKG.PublicKeyShares, 0, len(qualifyIDs))
+ for _, id := range qualifyIDs {
+ pubShares = append(pubShares, &mpkMap[id].PublicKeyShares)
+ }
+ groupPK := cryptoDKG.RecoverGroupPublicKey(pubShares)
+ return &GroupPublicKey{
+ Round: round,
+ QualifyIDs: qualifyIDs,
+ QualifyNodeIDs: qualifyNodeIDs,
+ IDMap: idMap,
+ Threshold: threshold,
+ GroupPublicKey: groupPK,
+ }, nil
+}
+
+// NodePublicKeys is the result of DKG protocol.
+type NodePublicKeys struct {
+ Round uint64
+ QualifyIDs cryptoDKG.IDs
+ QualifyNodeIDs map[types.NodeID]struct{}
+ IDMap map[types.NodeID]cryptoDKG.ID
+ PublicKeys map[types.NodeID]*cryptoDKG.PublicKey
+ Threshold int
+}
+
+// NewNodePublicKeys creats a NodePublicKeys instance.
+func NewNodePublicKeys(
+ round uint64,
+ mpks []*MasterPublicKey, complaints []*Complaint,
+ threshold int) (
+ *NodePublicKeys, error) {
+ qualifyIDs, qualifyNodeIDs, err :=
+ calcQualifyNodes(mpks, complaints, threshold)
+ if err != nil {
+ return nil, err
+ }
+ mpkMap := make(map[cryptoDKG.ID]*MasterPublicKey, cap(qualifyIDs))
+ idMap := make(map[types.NodeID]cryptoDKG.ID)
+ for _, mpk := range mpks {
+ if _, exist := qualifyNodeIDs[mpk.ProposerID]; !exist {
continue
}
mpkMap[mpk.DKGID] = mpk
idMap[mpk.ProposerID] = mpk.DKGID
- qualifyIDs = append(qualifyIDs, mpk.DKGID)
- qualifyNodeIDs[mpk.ProposerID] = struct{}{}
}
// Recover qualify members' public key.
pubKeys := make(map[types.NodeID]*cryptoDKG.PublicKey, len(qualifyIDs))
@@ -366,19 +428,12 @@ func NewGroupPublicKey(
}
pubKeys[mpkMap[recvID].ProposerID] = pubKey
}
- // Recover Group Public Key.
- pubShares := make([]*cryptoDKG.PublicKeyShares, 0, len(qualifyIDs))
- for _, id := range qualifyIDs {
- pubShares = append(pubShares, &mpkMap[id].PublicKeyShares)
- }
- groupPK := cryptoDKG.RecoverGroupPublicKey(pubShares)
- return &GroupPublicKey{
+ return &NodePublicKeys{
Round: round,
QualifyIDs: qualifyIDs,
QualifyNodeIDs: qualifyNodeIDs,
IDMap: idMap,
PublicKeys: pubKeys,
Threshold: threshold,
- GroupPublicKey: groupPK,
}, nil
}