aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go
diff options
context:
space:
mode:
authorWei-Ning Huang <w@dexon.org>2019-04-12 18:14:18 +0800
committerWei-Ning Huang <w@byzantine-lab.io>2019-06-15 22:09:55 +0800
commitd5daf97dba3156ef9adbf129a9d1e276f80d1095 (patch)
tree2d5d287865520cdb6fc6e6016e5010532e5e1e17 /vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go
parent12de2a1841d7725750c2757629178fcf65c60152 (diff)
downloadgo-tangerine-d5daf97dba3156ef9adbf129a9d1e276f80d1095.tar
go-tangerine-d5daf97dba3156ef9adbf129a9d1e276f80d1095.tar.gz
go-tangerine-d5daf97dba3156ef9adbf129a9d1e276f80d1095.tar.bz2
go-tangerine-d5daf97dba3156ef9adbf129a9d1e276f80d1095.tar.lz
go-tangerine-d5daf97dba3156ef9adbf129a9d1e276f80d1095.tar.xz
go-tangerine-d5daf97dba3156ef9adbf129a9d1e276f80d1095.tar.zst
go-tangerine-d5daf97dba3156ef9adbf129a9d1e276f80d1095.zip
dex: implement bad peer detect and disconnect mechanism (#360)
Diffstat (limited to 'vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go')
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go67
1 files changed, 55 insertions, 12 deletions
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go
index af0adf259..4597fe92b 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/agreement-mgr.go
@@ -24,6 +24,8 @@ import (
"sync"
"time"
+ lru "github.com/hashicorp/golang-lru"
+
"github.com/dexon-foundation/dexon-consensus/common"
"github.com/dexon-foundation/dexon-consensus/core/types"
typesDKG "github.com/dexon-foundation/dexon-consensus/core/types/dkg"
@@ -36,17 +38,34 @@ var (
ErrRoundOutOfRange = errors.New("round out of range")
ErrInvalidBlock = errors.New("invalid block")
ErrNoValidLeader = errors.New("no valid leader")
+ ErrIncorrectCRSSignature = errors.New("incorrect CRS signature")
+ ErrBlockTooOld = errors.New("block too old")
)
const maxResultCache = 100
+const settingLimit = 3
// genValidLeader generate a validLeader function for agreement modules.
func genValidLeader(
- mgr *agreementMgr) func(*types.Block) (bool, error) {
- return func(block *types.Block) (bool, error) {
+ mgr *agreementMgr) validLeaderFn {
+ return func(block *types.Block, crs common.Hash) (bool, error) {
if block.Timestamp.After(time.Now()) {
return false, nil
}
+ if block.Position.Round >= DKGDelayRound {
+ if mgr.recv.npks == nil {
+ return false, nil
+ }
+ if block.Position.Round > mgr.recv.npks.Round {
+ return false, nil
+ }
+ if block.Position.Round < mgr.recv.npks.Round {
+ return false, ErrBlockTooOld
+ }
+ }
+ if !utils.VerifyCRSSignature(block, crs, mgr.recv.npks) {
+ return false, ErrIncorrectCRSSignature
+ }
if err := mgr.bcModule.sanityCheck(block); err != nil {
if err == ErrRetrySanityCheckLater {
return false, nil
@@ -114,12 +133,15 @@ type agreementMgr struct {
recv *consensusBAReceiver
processedBAResult map[types.Position]struct{}
voteFilter *utils.VoteFilter
+ settingCache *lru.Cache
+ curRoundSetting *baRoundSetting
waitGroup sync.WaitGroup
isRunning bool
lock sync.RWMutex
}
func newAgreementMgr(con *Consensus) (mgr *agreementMgr, err error) {
+ settingCache, _ := lru.New(settingLimit)
mgr = &agreementMgr{
con: con,
ID: con.ID,
@@ -133,6 +155,7 @@ func newAgreementMgr(con *Consensus) (mgr *agreementMgr, err error) {
ctx: con.ctx,
processedBAResult: make(map[types.Position]struct{}, maxResultCache),
voteFilter: utils.NewVoteFilter(),
+ settingCache: settingCache,
}
mgr.recv = &consensusBAReceiver{
consensus: con,
@@ -149,21 +172,18 @@ func (mgr *agreementMgr) prepare() {
newLeaderSelector(genValidLeader(mgr), mgr.logger),
mgr.signer,
mgr.logger)
- nodes, err := mgr.cache.GetNodeSet(round)
- if err != nil {
+ setting := mgr.generateSetting(round)
+ if setting == nil {
+ mgr.logger.Warn("Unable to prepare init setting", "round", round)
return
}
- agr.notarySet = nodes.GetSubSet(
- int(mgr.config(round).notarySetSize),
- types.NewNotarySetTarget(mgr.config(round).crs))
+ mgr.curRoundSetting = setting
+ agr.notarySet = mgr.curRoundSetting.dkgSet
// Hacky way to make agreement module self contained.
mgr.recv.agreementModule = agr
mgr.baModule = agr
if round >= DKGDelayRound {
- setting := mgr.generateSetting(round)
- if setting == nil {
- mgr.logger.Warn("Unable to prepare init setting", "round", round)
- } else if _, exist := setting.dkgSet[mgr.ID]; exist {
+ if _, exist := setting.dkgSet[mgr.ID]; exist {
mgr.logger.Debug("Preparing signer and npks.", "round", round)
npk, signer, err := mgr.con.cfgModule.getDKGInfo(round, false)
if err != nil {
@@ -252,9 +272,25 @@ func (mgr *agreementMgr) notifyRoundEvents(evts []utils.RoundEventParam) error {
}
func (mgr *agreementMgr) processVote(v *types.Vote) (err error) {
+ if !mgr.recv.isNotary {
+ return nil
+ }
if mgr.voteFilter.Filter(v) {
return nil
}
+ if v.Position.Round == mgr.curRoundSetting.round {
+ if _, exist := mgr.curRoundSetting.dkgSet[v.ProposerID]; !exist {
+ return ErrNotInNotarySet
+ }
+ } else if v.Position.Round == mgr.curRoundSetting.round+1 {
+ setting := mgr.generateSetting(v.Position.Round)
+ if setting == nil {
+ return ErrConfigurationNotReady
+ }
+ if _, exist := setting.dkgSet[v.ProposerID]; !exist {
+ return ErrNotInNotarySet
+ }
+ }
if err = mgr.baModule.processVote(v); err == nil {
mgr.baModule.updateFilter(mgr.voteFilter)
mgr.voteFilter.AddVote(v)
@@ -323,6 +359,7 @@ func (mgr *agreementMgr) processAgreementResult(
result.Position.Round)
return ErrConfigurationNotReady
}
+ mgr.curRoundSetting = setting
leader, err := mgr.calcLeader(setting.dkgSet, setting.crs, result.Position)
if err != nil {
return err
@@ -358,6 +395,9 @@ func (mgr *agreementMgr) stop() {
}
func (mgr *agreementMgr) generateSetting(round uint64) *baRoundSetting {
+ if setting, exist := mgr.settingCache.Get(round); exist {
+ return setting.(*baRoundSetting)
+ }
curConfig := mgr.config(round)
if curConfig == nil {
return nil
@@ -383,13 +423,15 @@ func (mgr *agreementMgr) generateSetting(round uint64) *baRoundSetting {
return nil
}
}
- return &baRoundSetting{
+ setting := &baRoundSetting{
crs: curConfig.crs,
dkgSet: dkgSet,
round: round,
threshold: utils.GetBAThreshold(&types.Config{
NotarySetSize: curConfig.notarySetSize}),
}
+ mgr.settingCache.Add(round, setting)
+ return setting
}
func (mgr *agreementMgr) runBA(initRound uint64) {
@@ -449,6 +491,7 @@ Loop:
}
mgr.recv.isNotary = checkRound()
mgr.voteFilter = utils.NewVoteFilter()
+ mgr.voteFilter.Position.Round = currentRound
mgr.recv.emptyBlockHashMap = &sync.Map{}
if currentRound >= DKGDelayRound && mgr.recv.isNotary {
var err error