aboutsummaryrefslogtreecommitdiffstats
path: root/core/dkg-tsig-protocol.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/dkg-tsig-protocol.go')
-rw-r--r--core/dkg-tsig-protocol.go85
1 files changed, 85 insertions, 0 deletions
diff --git a/core/dkg-tsig-protocol.go b/core/dkg-tsig-protocol.go
index 795f6d3..1b5f547 100644
--- a/core/dkg-tsig-protocol.go
+++ b/core/dkg-tsig-protocol.go
@@ -19,6 +19,7 @@ package core
import (
"fmt"
+ "sync"
"github.com/dexon-foundation/dexon-consensus-core/common"
"github.com/dexon-foundation/dexon-consensus-core/core/crypto"
@@ -46,6 +47,8 @@ var (
"incorrect partialSignature")
ErrNotEnoughtPartialSignatures = fmt.Errorf(
"not enough of partial signatures")
+ ErrRoundAlreadyPurged = fmt.Errorf(
+ "cache of round already been purged")
)
type dkgReceiver interface {
@@ -95,6 +98,20 @@ type DKGGroupPublicKey struct {
threshold int
}
+// TSigVerifier is the interface verifying threshold signature.
+type TSigVerifier interface {
+ VerifySignature(hash common.Hash, sig crypto.Signature) bool
+}
+
+// TSigVerifierCache is the cache for TSigVerifier.
+type TSigVerifierCache struct {
+ gov Governance
+ verifier map[uint64]TSigVerifier
+ minRound uint64
+ cacheSize int
+ lock sync.RWMutex
+}
+
type tsigProtocol struct {
groupPublicKey *DKGGroupPublicKey
hash common.Hash
@@ -405,6 +422,74 @@ func (gpk *DKGGroupPublicKey) VerifySignature(
return gpk.groupPublicKey.VerifySignature(hash, sig)
}
+// NewTSigVerifierCache creats a DKGGroupPublicKey instance.
+func NewTSigVerifierCache(gov Governance, cacheSize int) *TSigVerifierCache {
+ return &TSigVerifierCache{
+ gov: gov,
+ verifier: make(map[uint64]TSigVerifier),
+ cacheSize: cacheSize,
+ }
+}
+
+// UpdateAndGet calls Update and then Get.
+func (tc *TSigVerifierCache) UpdateAndGet(round uint64) (
+ TSigVerifier, bool, error) {
+ ok, err := tc.Update(round)
+ if err != nil {
+ return nil, false, err
+ }
+ if !ok {
+ return nil, false, nil
+ }
+ v, ok := tc.Get(round)
+ return v, ok, nil
+}
+
+// Update the cache and returns if success.
+func (tc *TSigVerifierCache) Update(round uint64) (bool, error) {
+ tc.lock.Lock()
+ defer tc.lock.Unlock()
+ if round < tc.minRound {
+ return false, ErrRoundAlreadyPurged
+ }
+ if _, exist := tc.verifier[round]; exist {
+ return true, nil
+ }
+ if !tc.gov.IsDKGFinal(round) {
+ return false, nil
+ }
+ gpk, err := NewDKGGroupPublicKey(round,
+ tc.gov.DKGMasterPublicKeys(round),
+ tc.gov.DKGComplaints(round),
+ int(tc.gov.Configuration(round).DKGSetSize/3)+1)
+ if err != nil {
+ return false, err
+ }
+ if len(tc.verifier) == 0 {
+ tc.minRound = round
+ }
+ tc.verifier[round] = gpk
+ if len(tc.verifier) > tc.cacheSize {
+ delete(tc.verifier, tc.minRound)
+ }
+ for {
+ if _, exist := tc.verifier[tc.minRound]; !exist {
+ tc.minRound++
+ } else {
+ break
+ }
+ }
+ return true, nil
+}
+
+// Get the TSigVerifier of round and returns if it exists.
+func (tc *TSigVerifierCache) Get(round uint64) (TSigVerifier, bool) {
+ tc.lock.RLock()
+ defer tc.lock.RUnlock()
+ verifier, exist := tc.verifier[round]
+ return verifier, exist
+}
+
func newTSigProtocol(
gpk *DKGGroupPublicKey,
hash common.Hash) *tsigProtocol {