consensus: fix slash bug when validator set changing (#1162)

This commit is contained in:
Leon 2023-03-01 16:47:38 +08:00 committed by GitHub
parent d065c4859e
commit 2a76eb498d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 7 deletions

@ -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
}
}