Skip to content
This repository has been archived by the owner on Jun 17, 2022. It is now read-only.

Commit

Permalink
don't detect a duplicating instance until synced
Browse files Browse the repository at this point in the history
git cherry-pick 19ad9a
  • Loading branch information
a.guzev committed Jun 1, 2020
1 parent 8e9a040 commit 0e3c75f
Showing 1 changed file with 37 additions and 30 deletions.
67 changes: 37 additions & 30 deletions gossip/emitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,9 +334,8 @@ func (em *Emitter) createEvent(poolTxs map[common.Address]types.Transactions) *i
// not a validator
return nil
}
validators := em.world.Engine.GetValidators()

if synced, _, _ := em.logSyncStatus(em.isSynced()); !synced {
if synced := em.logSyncStatus(em.isSynced()); !synced {
// I'm reindexing my old events, so don't create events until connect all the existing self-events
return nil
}
Expand Down Expand Up @@ -402,6 +401,7 @@ func (em *Emitter) createEvent(poolTxs map[common.Address]types.Transactions) *i
}

// calc initial GasPower
validators := em.world.Engine.GetValidators()
event.GasPowerUsed = basiccheck.CalcGasPowerUsed(event, &em.net.Dag)
availableGasPower, err := em.world.Checkers.Gaspowercheck.CalcGasPower(&event.EventHeaderData, selfParentHeader)
if err != nil {
Expand Down Expand Up @@ -535,27 +535,32 @@ func (em *Emitter) OnNewEpoch(newValidators *pos.Validators, newEpoch idx.Epoch)

// OnNewEvent tracks new events to find out am I properly synced or not
func (em *Emitter) OnNewEvent(e *inter.Event) {
now := time.Now()
myStakerID := em.myStakerID
if em.myStakerID != 0 && em.syncStatus.prevLocalEmittedID != e.Hash() {
if e.Creator == myStakerID {
// event was emitted by me on another instance
em.syncStatus.prevExternalEmittedTime = now

passedSinceEvent := time.Since(inter.MaxTimestamp(e.ClaimedTime, e.MedianTime).Time())
threshold := em.intervals.SelfForkProtection
if threshold > time.Minute {
threshold = time.Minute
}
if passedSinceEvent <= threshold {
reason := "Received a recent event (event id=%s) from this validator (staker id=%d) which wasn't created on this node.\n" +
"This external event was created %s, %s ago at the time of this error.\n" +
"It means that a duplicating instance of the same validator is running simultaneously, which will eventually lead to a doublesign.\n" +
"For now, doublesign was prevented by one of the heuristics, but next time you (and your delegators) may lose the stake."
errlock.Permanent(fmt.Errorf(reason, e.Hash().String(), myStakerID, e.ClaimedTime.Time().Local().String(), passedSinceEvent.String()))
}
}
if em.myStakerID == 0 || em.myStakerID != e.Creator {
return
}
if em.syncStatus.prevLocalEmittedID == e.Hash() {
return
}

// event was emitted by me on another instance
em.syncStatus.prevExternalEmittedTime = time.Now()
if synced, _, _ := em.isSynced(); !synced {
return
}

passedSinceEvent := time.Since(inter.MaxTimestamp(e.ClaimedTime, e.MedianTime).Time())
threshold := em.intervals.SelfForkProtection
if threshold > time.Minute {
threshold = time.Minute
}
if passedSinceEvent <= threshold {
reason := "Received a recent event (event id=%s) from this validator (staker id=%d) which wasn't created on this node.\n" +
"This external event was created %s, %s ago at the time of this error.\n" +
"It means that a duplicating instance of the same validator is running simultaneously, which will eventually lead to a doublesign.\n" +
"For now, doublesign was prevented by one of the heuristics, but next time you (and your delegators) may lose the stake."
errlock.Permanent(fmt.Errorf(reason, e.Hash().String(), em.myStakerID, e.ClaimedTime.Time().Local().String(), passedSinceEvent.String()))
}

}

func (em *Emitter) isSynced() (bool, string, time.Duration) {
Expand Down Expand Up @@ -588,15 +593,17 @@ func (em *Emitter) isSynced() (bool, string, time.Duration) {
return true, "", 0
}

func (em *Emitter) logSyncStatus(synced bool, reason string, wait time.Duration) (bool, string, time.Duration) {
if !synced {
if wait == 0 {
em.Periodic.Info(25*time.Second, "Emitting is paused", "reason", reason)
} else {
em.Periodic.Info(25*time.Second, "Emitting is paused", "reason", reason, "wait", wait)
}
func (em *Emitter) logSyncStatus(synced bool, reason string, wait time.Duration) bool {
if synced {
return true
}

if wait == 0 {
em.Periodic.Info(25*time.Second, "Emitting is paused", "reason", reason)
} else {
em.Periodic.Info(25*time.Second, "Emitting is paused", "reason", reason, "wait", wait)
}
return synced, reason, wait
return false
}

// return true if event is in epoch tail (unlikely to confirm)
Expand Down

0 comments on commit 0e3c75f

Please sign in to comment.