consensus: fix slash bug when validator set changing (#1162)
This commit is contained in:
parent
d065c4859e
commit
2a76eb498d
@ -1298,7 +1298,7 @@ func encodeSigHeader(w io.Writer, header *types.Header, chainId *big.Int) {
|
||||
}
|
||||
}
|
||||
|
||||
func backOffTime(snap *Snapshot, val common.Address) uint64 {
|
||||
func (p *Parlia) backOffTime(snap *Snapshot, header *types.Header, val common.Address) uint64 {
|
||||
if snap.inturn(val) {
|
||||
return 0
|
||||
} else {
|
||||
@ -1311,8 +1311,10 @@ func backOffTime(snap *Snapshot, val common.Address) uint64 {
|
||||
r := rand.New(s)
|
||||
n := len(snap.Validators)
|
||||
backOffSteps := make([]uint64, 0, n)
|
||||
for idx := uint64(0); idx < uint64(n); idx++ {
|
||||
backOffSteps = append(backOffSteps, idx)
|
||||
|
||||
if !p.chainConfig.IsBohr(header.Number) {
|
||||
for i := uint64(0); i < uint64(n); i++ {
|
||||
backOffSteps = append(backOffSteps, i)
|
||||
}
|
||||
r.Shuffle(n, func(i, j int) {
|
||||
backOffSteps[i], backOffSteps[j] = backOffSteps[j], backOffSteps[i]
|
||||
@ -1320,6 +1322,41 @@ func backOffTime(snap *Snapshot, val common.Address) uint64 {
|
||||
delay := initialBackOffTime + backOffSteps[idx]*wiggleTime
|
||||
return delay
|
||||
}
|
||||
|
||||
// Exclude the recently signed validators first, and then compute the backOffTime.
|
||||
recentVals := make(map[common.Address]bool, len(snap.Recents))
|
||||
//for seen, recent := range snap.Recents {
|
||||
for _, recent := range snap.Recents {
|
||||
if val == recent {
|
||||
// The backOffTime does not matter when a validator has signed recently.
|
||||
return 0
|
||||
}
|
||||
recentVals[recent] = true
|
||||
}
|
||||
|
||||
backOffIndex := idx
|
||||
validators := snap.validators()
|
||||
for i := 0; i < n; i++ {
|
||||
if isRecent, ok := recentVals[validators[i]]; ok && isRecent {
|
||||
if i < idx {
|
||||
backOffIndex--
|
||||
}
|
||||
continue
|
||||
}
|
||||
backOffSteps = append(backOffSteps, uint64(len(backOffSteps)))
|
||||
}
|
||||
r.Shuffle(len(backOffSteps), func(i, j int) {
|
||||
backOffSteps[i], backOffSteps[j] = backOffSteps[j], backOffSteps[i]
|
||||
})
|
||||
delay := initialBackOffTime + backOffSteps[backOffIndex]*wiggleTime
|
||||
|
||||
// If the in turn validator has recently signed, no initial delay.
|
||||
inTurnVal := validators[(snap.Number+1)%uint64(len(validators))]
|
||||
if isRecent, ok := recentVals[inTurnVal]; ok && isRecent {
|
||||
delay -= initialBackOffTime
|
||||
}
|
||||
return delay
|
||||
}
|
||||
}
|
||||
|
||||
// chain context
|
||||
|
@ -29,14 +29,14 @@ func (p *Parlia) delayForRamanujanFork(snap *Snapshot, header *types.Header) tim
|
||||
func (p *Parlia) blockTimeForRamanujanFork(snap *Snapshot, header, parent *types.Header) uint64 {
|
||||
blockTime := parent.Time + p.config.Period
|
||||
if p.chainConfig.IsRamanujan(header.Number) {
|
||||
blockTime = blockTime + backOffTime(snap, p.val)
|
||||
blockTime = blockTime + p.backOffTime(snap, header, p.val)
|
||||
}
|
||||
return blockTime
|
||||
}
|
||||
|
||||
func (p *Parlia) blockTimeVerifyForRamanujanFork(snap *Snapshot, header, parent *types.Header) error {
|
||||
if p.chainConfig.IsRamanujan(header.Number) {
|
||||
if header.Time < parent.Time+p.config.Period+backOffTime(snap, header.Coinbase) {
|
||||
if header.Time < parent.Time+p.config.Period+p.backOffTime(snap, header, header.Coinbase) {
|
||||
return consensus.ErrFutureBlock
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user