aboutsummaryrefslogtreecommitdiffstats
path: root/core/governance.go
diff options
context:
space:
mode:
authorWei-Ning Huang <w@dexon.org>2019-04-03 22:47:05 +0800
committerWei-Ning Huang <w@dexon.org>2019-04-09 21:32:59 +0800
commitb8eb11fc1ecba52c05ea150cf77217e61bb16c55 (patch)
tree46d5203f72303d45194a13a375364c3a7972be40 /core/governance.go
parentc32e7ba03af9360a7797acdcb5fed2691ef75f9c (diff)
downloaddexon-b8eb11fc1ecba52c05ea150cf77217e61bb16c55.tar
dexon-b8eb11fc1ecba52c05ea150cf77217e61bb16c55.tar.gz
dexon-b8eb11fc1ecba52c05ea150cf77217e61bb16c55.tar.bz2
dexon-b8eb11fc1ecba52c05ea150cf77217e61bb16c55.tar.lz
dexon-b8eb11fc1ecba52c05ea150cf77217e61bb16c55.tar.xz
dexon-b8eb11fc1ecba52c05ea150cf77217e61bb16c55.tar.zst
dexon-b8eb11fc1ecba52c05ea150cf77217e61bb16c55.zip
core: add cache for DKG MPK and complaint (#334)
Since deserializing DKG related items are extremely slow (takes about 3 seconds for 100 items), we cache it in the governance interface.
Diffstat (limited to 'core/governance.go')
-rw-r--r--core/governance.go85
1 files changed, 69 insertions, 16 deletions
diff --git a/core/governance.go b/core/governance.go
index 0ebc942be..39b2704e6 100644
--- a/core/governance.go
+++ b/core/governance.go
@@ -4,6 +4,7 @@ import (
"encoding/hex"
"fmt"
"math/big"
+ "sync"
"time"
coreCommon "github.com/dexon-foundation/dexon-consensus/common"
@@ -13,15 +14,17 @@ import (
coreTypes "github.com/dexon-foundation/dexon-consensus/core/types"
dkgTypes "github.com/dexon-foundation/dexon-consensus/core/types/dkg"
coreUtils "github.com/dexon-foundation/dexon-consensus/core/utils"
+ "github.com/hashicorp/golang-lru/simplelru"
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/vm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/log"
- "github.com/dexon-foundation/dexon/rlp"
)
+const dkgCacheSize = 5
+
type GovernanceStateDB interface {
State() (*state.StateDB, error)
StateAt(height uint64) (*state.StateDB, error)
@@ -47,13 +50,32 @@ func (g *governanceStateDB) StateAt(height uint64) (*state.StateDB, error) {
return g.bc.StateAt(header.Root)
}
+type dkgCacheItem struct {
+ Round uint64
+ Reset uint64
+ MasterPublicKeysLen uint64
+ MasterPublicKeys []*dkgTypes.MasterPublicKey
+ ComplaintsLen uint64
+ Complaints []*dkgTypes.Complaint
+}
+
type Governance struct {
db GovernanceStateDB
nodeSetCache *dexCore.NodeSetCache
+ dkgCache *simplelru.LRU
+ dkgCacheMu sync.RWMutex
}
func NewGovernance(db GovernanceStateDB) *Governance {
- g := &Governance{db: db}
+ cache, err := simplelru.NewLRU(dkgCacheSize, nil)
+ if err != nil {
+ log.Error("Failed to initialize DKG cache", "error", err)
+ return nil
+ }
+ g := &Governance{
+ db: db,
+ dkgCache: cache,
+ }
g.nodeSetCache = dexCore.NewNodeSetCache(g)
return g
}
@@ -210,29 +232,60 @@ func (g *Governance) DKGSetNodeKeyAddresses(round uint64) (map[common.Address]st
return r, nil
}
-func (g *Governance) DKGComplaints(round uint64) []*dkgTypes.Complaint {
+func (g *Governance) getOrUpdateDKGCache(round uint64) *dkgCacheItem {
s := g.GetStateForDKGAtRound(round)
if s == nil {
+ log.Error("Failed to get DKG state", "round", round)
return nil
}
+ reset := s.DKGResetCount(new(big.Int).SetUint64(round))
+ mpksLen := s.LenDKGMasterPublicKeys().Uint64()
+ compsLen := s.LenDKGComplaints().Uint64()
- var dkgComplaints []*dkgTypes.Complaint
- for _, pk := range s.DKGComplaints() {
- x := new(dkgTypes.Complaint)
- if err := rlp.DecodeBytes(pk, x); err != nil {
- panic(err)
- }
- dkgComplaints = append(dkgComplaints, x)
+ var cache *dkgCacheItem
+
+ g.dkgCacheMu.RLock()
+ if v, ok := g.dkgCache.Get(round); ok {
+ cache = v.(*dkgCacheItem)
+ }
+ g.dkgCacheMu.RUnlock()
+
+ if cache != nil && cache.Reset == reset.Uint64() &&
+ cache.MasterPublicKeysLen == mpksLen &&
+ cache.ComplaintsLen == compsLen {
+ return cache
+ }
+
+ g.dkgCacheMu.Lock()
+ defer g.dkgCacheMu.Unlock()
+
+ cache = &dkgCacheItem{
+ Round: round,
+ Reset: reset.Uint64(),
+ }
+
+ if cache == nil || cache.MasterPublicKeysLen != mpksLen {
+ cache.MasterPublicKeys = s.DKGMasterPublicKeyItems()
+ cache.MasterPublicKeysLen = uint64(len(cache.MasterPublicKeys))
}
- return dkgComplaints
+
+ if cache == nil || cache.ComplaintsLen != compsLen {
+ cache.Complaints = s.DKGComplaintItems()
+ cache.ComplaintsLen = uint64(len(cache.Complaints))
+ }
+
+ g.dkgCache.Add(round, cache)
+ return cache
+}
+
+func (g *Governance) DKGComplaints(round uint64) []*dkgTypes.Complaint {
+ cache := g.getOrUpdateDKGCache(round)
+ return cache.Complaints
}
func (g *Governance) DKGMasterPublicKeys(round uint64) []*dkgTypes.MasterPublicKey {
- s := g.GetStateForDKGAtRound(round)
- if s == nil {
- return nil
- }
- return s.UniqueDKGMasterPublicKeys()
+ cache := g.getOrUpdateDKGCache(round)
+ return cache.MasterPublicKeys
}
func (g *Governance) IsDKGMPKReady(round uint64) bool {