Skip to content

Commit

Permalink
fix: recently signed check when slashing unavailable validator (axiei…
Browse files Browse the repository at this point in the history
…nfinity#267)

The first validator in snap.Recents is shifted out and allowed to seal the block
already. However, when determining if we should slash the validator we mark that
first validator as unable to seal block which is incorrect. This loosens the
slash check rule. This commit fix this bug and create a separate helper function
to check if the validator recently signed a block.
  • Loading branch information
minh-bq committed Apr 26, 2023
1 parent d046ca1 commit b4da4d0
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 38 deletions.
41 changes: 13 additions & 28 deletions consensus/consortium/v2/consortium.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,13 +452,8 @@ func (c *Consortium) verifySeal(chain consensus.ChainHeaderReader, header *types
return errUnauthorizedValidator
}

for seen, recent := range snap.Recents {
if recent == signer {
// Signer is among recents, only fail if the current block doesn't shift it out
if limit := uint64(len(snap.Validators)/2 + 1); seen > number-limit {
return consortiumCommon.ErrRecentlySigned
}
}
if snap.IsRecentlySigned(signer) {
return consortiumCommon.ErrRecentlySigned
}

// Ensure that the difficulty corresponds to the turn-ness of the signer
Expand Down Expand Up @@ -617,10 +612,14 @@ func (c *Consortium) processSystemTransactions(chain consensus.ChainHeaderReader
}
spoiledVal := snap.supposeValidator()
signedRecently := false
for _, recent := range snap.Recents {
if recent == spoiledVal {
signedRecently = true
break
if c.chainConfig.IsOlek(header.Number) {
signedRecently = snap.IsRecentlySigned(spoiledVal)
} else {
for _, recent := range snap.Recents {
if recent == spoiledVal {
signedRecently = true
break
}
}
}
if !signedRecently {
Expand Down Expand Up @@ -821,13 +820,8 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block,
}

// If we're amongst the recent signers, wait for the next block
for seen, recent := range snap.Recents {
if recent == val {
// Signer is among recents, only wait if the current block doesn't shift it out
if limit := uint64(len(snap.Validators)/2 + 1); number < limit || seen > number-limit {
return consortiumCommon.ErrRecentlySigned
}
}
if snap.IsRecentlySigned(val) {
return consortiumCommon.ErrRecentlySigned
}

// Sweet, the protocol permits us to sign the block, wait for our time
Expand Down Expand Up @@ -945,16 +939,7 @@ func (c *Consortium) GetBestParentBlock(chain *core.BlockChain) (*types.Block, b
// Miner can create an inturn block which helps the chain to have
// greater diffculty
if snap.supposeValidator() == signer {
inRecent := false
for seen, recent := range snap.Recents {
if recent == signer {
if limit := uint64(len(snap.Validators)/2 + 1); seen > snap.Number+1-limit {
inRecent = true
break
}
}
}
if !inRecent {
if !snap.IsRecentlySigned(signer) {
return prevBlock, true
}
}
Expand Down
22 changes: 12 additions & 10 deletions consensus/consortium/v2/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,16 +228,7 @@ func (s *Snapshot) sealableValidators(validator common.Address) (position, numOf
validators := s.validators()
sealable := make([]common.Address, 0, len(validators))
for _, val := range validators {
allowToSeal := true
for seen, recent := range s.Recents {
if recent == val {
if limit := uint64(len(validators)/2 + 1); seen > s.Number+1-limit {
allowToSeal = false
break
}
}
}
if allowToSeal {
if !s.IsRecentlySigned(val) {
sealable = append(sealable, val)
}
}
Expand All @@ -259,6 +250,17 @@ func (s *Snapshot) supposeValidator() common.Address {
return validators[index]
}

func (s *Snapshot) IsRecentlySigned(validator common.Address) bool {
for seen, recent := range s.Recents {
if recent == validator {
if limit := uint64(len(s.Validators)/2 + 1); seen > s.Number+1-limit {
return true
}
}
}
return false
}

// ParseValidators retrieves the list of validators
func ParseValidators(validatorsBytes []byte) ([]common.Address, error) {
if len(validatorsBytes)%validatorBytesLength != 0 {
Expand Down

0 comments on commit b4da4d0

Please sign in to comment.