Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Primed for suspension #1293

Merged
merged 21 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased changes

- Automatically suspend validators from the consensus that missed too many
rounds in the previous payday.
- Add support for suspend/resume to validator configuration updates.
- Validators that are suspended are paused from participating in the consensus algorithm.
- Add `GetConsensusDetailedStatus` gRPC endpoint for getting detailed information on the status
Expand Down
26 changes: 26 additions & 0 deletions concordium-consensus/src/Concordium/GlobalState/BlockState.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1530,6 +1530,28 @@ class (BlockStateQuery m) => BlockStateOperations m where
-- round did timeout.
bsoUpdateMissedRounds :: (PVSupportsDelegation (MPV m), PVSupportsValidatorSuspension (MPV m)) => UpdatableBlockState m -> Map.Map BakerId Word64 -> m (UpdatableBlockState m)

-- | Mark given validators for possible suspension at the next snapshot
-- epoch. Returns the subset of the given validator ids whose missed rounds
-- exceeded the given threshold and are now primed for suspension.
bsoPrimeForSuspension ::
(PVSupportsDelegation (MPV m), PVSupportsValidatorSuspension (MPV m)) =>
UpdatableBlockState m ->
-- | The threshold for maximal missed rounds
Word64 ->
-- | The set of validators that are considered for suspension. This
-- should be the current payday validators.
[BakerId] ->
-- | Returns the subset of primed validator ids and the updated block state
m ([BakerId], UpdatableBlockState m)

-- | Suspend validators with the given account indices, if
-- 1) the account index points to an existing account
-- 2) the account belongs to a validator
-- 3) the account was not already suspended
-- Returns the subset of account indices that were suspended together with their canonical
-- addresses.
bsoSuspendValidators :: (PVSupportsValidatorSuspension (MPV m)) => UpdatableBlockState m -> [AccountIndex] -> m ([(AccountIndex, AccountAddress)], UpdatableBlockState m)

-- | A snapshot of the block state that can be used to roll back to a previous state.
type StateSnapshot m

Expand Down Expand Up @@ -1850,6 +1872,8 @@ instance (Monad (t m), MonadTrans t, BlockStateOperations m) => BlockStateOperat
bsoSetRewardAccounts s = lift . bsoSetRewardAccounts s
bsoIsProtocolUpdateEffective = lift . bsoIsProtocolUpdateEffective
bsoUpdateMissedRounds s = lift . bsoUpdateMissedRounds s
bsoPrimeForSuspension s t = lift . bsoPrimeForSuspension s t
bsoSuspendValidators s = lift . bsoSuspendValidators s
type StateSnapshot (MGSTrans t m) = StateSnapshot m
bsoSnapshotState = lift . bsoSnapshotState
bsoRollback s = lift . bsoRollback s
Expand Down Expand Up @@ -1907,6 +1931,8 @@ instance (Monad (t m), MonadTrans t, BlockStateOperations m) => BlockStateOperat
{-# INLINE bsoGetCurrentEpochBakers #-}
{-# INLINE bsoIsProtocolUpdateEffective #-}
{-# INLINE bsoUpdateMissedRounds #-}
{-# INLINE bsoPrimeForSuspension #-}
{-# INLINE bsoSuspendValidators #-}
{-# INLINE bsoSnapshotState #-}
{-# INLINE bsoRollback #-}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3509,6 +3509,87 @@ doUpdateMissedRounds pbs rds = do
(Map.toList rds)
storePBS pbs bsp'

-- | Prime validators for suspension. Returns the subset of the given validator
-- ids whose missed rounds exceeded the given threshold and are now primed for
-- suspension.
doPrimeForSuspension ::
( PVSupportsDelegation pv,
SupportsPersistentState pv m
) =>
PersistentBlockState pv ->
Word64 ->
[BakerId] ->
m ([BakerId], PersistentBlockState pv)
doPrimeForSuspension pbs threshold bids = do
drsk0 marked this conversation as resolved.
Show resolved Hide resolved
bprds <- doGetBakerPoolRewardDetails pbs
bsp0 <- loadPBS pbs
(bidsUpd, bsp') <- do
foldM
( \res@(acc, bsp) bId -> do
let mBprd = Map.lookup bId bprds
case mBprd of
Just bprd
| CTrue SuspensionInfo{..} <- suspensionInfo bprd,
missedRounds > threshold -> do
bsp' <-
modifyBakerPoolRewardDetailsInPoolRewards
bsp
bId
(\bpr -> bpr{suspensionInfo = (\suspInfo -> suspInfo{primedForSuspension = True}) <$> suspensionInfo bpr})
return (bId : acc, bsp')
_otherwise -> return res
)
([], bsp0)
bids
pbs' <- storePBS pbs bsp'
return (bidsUpd, pbs')

-- | Suspend validators with the given account indices, if
-- 1) the account index points to an existing account
-- 2) the account belongs to a validator
-- 3) the account was not already suspended
-- Returns the subset of account indices that were suspended together with their canonical account
-- addresses.
doSuspendValidators ::
forall pv m.
( SupportsPersistentState pv m
) =>
PersistentBlockState pv ->
[AccountIndex] ->
m ([(AccountIndex, AccountAddress)], PersistentBlockState pv)
doSuspendValidators pbs ais =
case hasValidatorSuspension of
STrue -> do
bsp0 <- loadPBS pbs
(aisSusp, bspUpd) <-
foldM
( \res@(aisSusp, bsp) ai -> do
mAcc <- Accounts.indexedAccount ai (bspAccounts bsp)
case mAcc of
Nothing -> return res
Just acc -> do
mValidatorExists <- accountBaker acc
case mValidatorExists of
Nothing -> return res
Just ba
-- The validator is not yet suspended
| False <-
uncond $ BaseAccounts._bieAccountIsSuspended $ _accountBakerInfo ba -> do
newAcc <- setAccountValidatorSuspended True acc
newAccounts <- Accounts.setAccountAtIndex ai newAcc (bspAccounts bsp)
address <- accountCanonicalAddress newAcc
return ((ai, address) : aisSusp, bsp{bspAccounts = newAccounts})
-- The validator is already suspended, nothing to do
| otherwise -> return res
)
([], bsp0)
ais
pbsUpd <- storePBS pbs bspUpd
return (aisSusp, pbsUpd)
SFalse -> return ([], pbs)
where
hasValidatorSuspension = sSupportsValidatorSuspension (accountVersion @(AccountVersionFor pv))

doProcessUpdateQueues ::
forall pv m.
(SupportsPersistentState pv m) =>
Expand Down Expand Up @@ -4455,6 +4536,8 @@ instance (IsProtocolVersion pv, PersistentState av pv r m) => BlockStateOperatio
bsoSetRewardAccounts = doSetRewardAccounts
bsoIsProtocolUpdateEffective = doIsProtocolUpdateEffective
bsoUpdateMissedRounds = doUpdateMissedRounds
bsoPrimeForSuspension = doPrimeForSuspension
bsoSuspendValidators = doSuspendValidators
type StateSnapshot (PersistentBlockStateMonad pv r m) = BlockStatePointers pv
bsoSnapshotState = loadPBS
bsoRollback = storePBS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@ instance
hMinBlockTimeQueue <- hashWhenSupported pMinBlockTimeQueue
hBlockEnergyLimitQueue <- hashWhenSupported pBlockEnergyLimitQueue
hFinalizationCommitteeParametersQueue <- hashWhenSupported pFinalizationCommitteeParametersQueue
hValidatorScoreParametersQueue <- hashWhenSupported pValidatorScoreParametersQueue
return $!
H.hash $
hRootKeysUpdateQueue
Expand All @@ -515,6 +516,7 @@ instance
<> hMinBlockTimeQueue
<> hBlockEnergyLimitQueue
<> hFinalizationCommitteeParametersQueue
<> hValidatorScoreParametersQueue
where
hashWhenSupported :: (MHashableTo m H.Hash a) => OParam pt cpv a -> m BS.ByteString
hashWhenSupported = maybeWhenSupported (return mempty) (fmap H.hashToByteString . getHashM)
Expand Down
Loading
Loading