aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMission Liao <mission.liao@dexon.org>2018-12-28 17:51:01 +0800
committerGitHub <noreply@github.com>2018-12-28 17:51:01 +0800
commitf12b6cf891181a72914b3aec8caf7ae0879f6000 (patch)
tree1900be3bbb2dcdb1b6ee9cc7e363a4b1e907369e
parent17884041681c4723d67792c19a1716b9e21fc146 (diff)
downloaddexon-consensus-f12b6cf891181a72914b3aec8caf7ae0879f6000.tar
dexon-consensus-f12b6cf891181a72914b3aec8caf7ae0879f6000.tar.gz
dexon-consensus-f12b6cf891181a72914b3aec8caf7ae0879f6000.tar.bz2
dexon-consensus-f12b6cf891181a72914b3aec8caf7ae0879f6000.tar.lz
dexon-consensus-f12b6cf891181a72914b3aec8caf7ae0879f6000.tar.xz
dexon-consensus-f12b6cf891181a72914b3aec8caf7ae0879f6000.tar.zst
dexon-consensus-f12b6cf891181a72914b3aec8caf7ae0879f6000.zip
sync: fix panic (#388)
* Merge several CRS notifications into one. * Sync config when new CRS is found
-rw-r--r--core/syncer/consensus.go79
1 files changed, 47 insertions, 32 deletions
diff --git a/core/syncer/consensus.go b/core/syncer/consensus.go
index bd58231..d334bbd 100644
--- a/core/syncer/consensus.go
+++ b/core/syncer/consensus.go
@@ -262,6 +262,9 @@ func (con *Consensus) ensureAgreementOverlapRound() bool {
for r = range tipRoundMap {
break
}
+ con.logger.Info("check agreement round cut",
+ "tip-round", r,
+ "configs", len(con.configs))
if tipRoundMap[r] == con.configs[r].NumChains {
con.agreementRoundCut = r
con.logger.Debug("agreement round cut found, round", r)
@@ -558,28 +561,12 @@ func (con *Consensus) buildEmptyBlock(b *types.Block, parent *types.Block) {
b.Acks = common.NewSortedHashes(common.Hashes{parent.Hash})
}
-// setupConfigs is called by SyncBlocks with blocks from compaction chain. In
-// the first time, setupConfigs setups from round 0.
-func (con *Consensus) setupConfigs(blocks []*types.Block) {
- // Find max round in blocks.
- var maxRound uint64
- for _, b := range blocks {
- if b.Position.Round > maxRound {
- maxRound = b.Position.Round
- }
- }
- // Get configs from governance.
- //
- // In fullnode, the notification of new round is yet another TX, which
- // needs to be executed after corresponding block delivered. Thus, the
- // configuration for 'maxRound + core.ConfigRoundShift' won't be ready when
- // seeing this block.
- untilRound := maxRound + core.ConfigRoundShift - 1
+func (con *Consensus) setupConfigsUntilRound(round uint64) {
curMaxNumChains := uint32(0)
func() {
con.lock.Lock()
defer con.lock.Unlock()
- for r := uint64(len(con.configs)); r <= untilRound; r++ {
+ for r := uint64(len(con.configs)); r <= round; r++ {
cfg := utils.GetConfigWithPanic(con.gov, r, con.logger)
con.configs = append(con.configs, cfg)
con.roundBeginTimes = append(
@@ -589,19 +576,41 @@ func (con *Consensus) setupConfigs(blocks []*types.Block) {
curMaxNumChains = cfg.NumChains
}
}
+ // Notify core.Lattice for new configs.
+ if con.lattice != nil {
+ for con.latticeLastRound+1 <= round {
+ con.latticeLastRound++
+ if err := con.lattice.AppendConfig(
+ con.latticeLastRound,
+ con.configs[con.latticeLastRound]); err != nil {
+ panic(err)
+ }
+ }
+ }
}()
con.resizeByNumChains(curMaxNumChains)
- // Notify core.Lattice for new configs.
- if con.lattice != nil {
- for con.latticeLastRound+1 <= untilRound {
- con.latticeLastRound++
- if err := con.lattice.AppendConfig(
- con.latticeLastRound,
- con.configs[con.latticeLastRound]); err != nil {
- panic(err)
- }
+}
+
+// setupConfigs is called by SyncBlocks with blocks from compaction chain. In
+// the first time, setupConfigs setups from round 0.
+func (con *Consensus) setupConfigs(blocks []*types.Block) {
+ // Find max round in blocks.
+ var maxRound uint64
+ for _, b := range blocks {
+ if b.Position.Round > maxRound {
+ maxRound = b.Position.Round
}
}
+ con.logger.Info("syncer setupConfigs",
+ "max", maxRound,
+ "lattice", con.latticeLastRound)
+ // Get configs from governance.
+ //
+ // In fullnode, the notification of new round is yet another TX, which
+ // needs to be executed after corresponding block delivered. Thus, the
+ // configuration for 'maxRound + core.ConfigRoundShift' won't be ready when
+ // seeing this block.
+ con.setupConfigsUntilRound(maxRound + core.ConfigRoundShift - 1)
}
// resizeByNumChains resizes fake lattice and agreement if numChains increases.
@@ -719,12 +728,13 @@ func (con *Consensus) startCRSMonitor() {
var lastNotifiedRound uint64
// Notify all agreements for new CRS.
notifyNewCRS := func(round uint64) {
+ con.setupConfigsUntilRound(round)
+ con.lock.Lock()
+ defer con.lock.Unlock()
if round == lastNotifiedRound {
return
}
- con.logger.Debug("CRS is ready", "round", round)
- con.lock.RLock()
- defer con.lock.RUnlock()
+ con.logger.Info("CRS is ready", "round", round)
lastNotifiedRound = round
for _, a := range con.agreements {
a.inputChan <- round
@@ -741,8 +751,13 @@ func (con *Consensus) startCRSMonitor() {
}
// Notify agreement modules for the latest round that CRS is
// available if the round is not notified yet.
- if (con.gov.CRS(lastNotifiedRound+1) != common.Hash{}) {
- notifyNewCRS(lastNotifiedRound + 1)
+ checked := lastNotifiedRound + 1
+ for (con.gov.CRS(checked) != common.Hash{}) {
+ checked++
+ }
+ checked--
+ if checked > lastNotifiedRound {
+ notifyNewCRS(checked)
}
}
}()