Skip to content

Commit d5e453f

Browse files
committed
Refactor PState update logic to handle stake undelegation/redelegation
uniformly across eras
1 parent 34a75b3 commit d5e453f

File tree

4 files changed

+54
-57
lines changed

4 files changed

+54
-57
lines changed

eras/conway/impl/src/Cardano/Ledger/Conway/Rules/Deleg.hs

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ import Control.State.Transition (
6767
State,
6868
TRC (TRC),
6969
TransitionRule,
70+
failBecause,
7071
failOnJust,
7172
judgmentContext,
7273
transitionRules,
@@ -204,7 +205,7 @@ conwayDelegTransition = do
204205
checkStakeKeyIsRegistered stakeCred = do
205206
let mAccountState = lookupAccountState stakeCred accounts
206207
isJust mAccountState ?! StakeKeyNotRegisteredDELEG stakeCred
207-
pure $ mAccountState >>= accountStateDelegatee
208+
pure mAccountState
208209
checkStakeDelegateeRegistered =
209210
let checkPoolRegistered targetPool =
210211
targetPool `Map.member` pools ?! DelegateeStakePoolNotRegisteredDELEG targetPool
@@ -253,18 +254,23 @@ conwayDelegTransition = do
253254
guard (balanceCompact /= mempty)
254255
Just $ fromCompact balanceCompact
255256
failOnJust checkInvalidRefund id
256-
isJust mAccountState ?! StakeKeyNotRegisteredDELEG stakeCred
257257
failOnJust checkStakeKeyHasZeroRewardBalance StakeKeyHasNonZeroRewardAccountBalanceDELEG
258-
pure $
259-
certState
260-
& certDStateL . accountsL .~ newAccounts
261-
& certVStateL %~ unDelegDRep stakeCred mCurDelegatee
262-
& certPStateL %~ unDelegStakePool stakeCred mCurDelegatee Nothing
258+
case mAccountState of
259+
Nothing ->
260+
do
261+
failBecause $ StakeKeyNotRegisteredDELEG stakeCred
262+
pure certState
263+
Just accountState ->
264+
pure $
265+
certState
266+
& certDStateL . accountsL .~ newAccounts
267+
& certVStateL %~ unDelegDRep stakeCred mCurDelegatee
268+
& certPStateL %~ unDelegReDelegStakePool stakeCred accountState Nothing
263269
ConwayDelegCert stakeCred delegatee -> do
264-
mCurDelegatee <- checkStakeKeyIsRegistered stakeCred
270+
mAccountState <- checkStakeKeyIsRegistered stakeCred
265271
checkStakeDelegateeRegistered delegatee
266272
pure $
267-
processDelegationInternal (pvMajor pv < natVersion @10) stakeCred mCurDelegatee delegatee certState
273+
processDelegationInternal (pvMajor pv < natVersion @10) stakeCred mAccountState delegatee certState
268274
ConwayRegDelegCert stakeCred delegatee deposit -> do
269275
checkDepositAgainstPParams deposit
270276
checkStakeKeyNotRegistered stakeCred
@@ -287,9 +293,8 @@ processDelegation ::
287293
CertState era
288294
processDelegation stakeCred newDelegatee !certState = certState'
289295
where
290-
!certState' = processDelegationInternal False stakeCred mCurDelegatee newDelegatee certState
296+
!certState' = processDelegationInternal False stakeCred mAccountState newDelegatee certState
291297
mAccountState = Map.lookup stakeCred (certState ^. certDStateL . accountsL . accountsMapL)
292-
mCurDelegatee = mAccountState >>= accountStateDelegatee
293298

294299
-- | Same as `processDelegation`, except it expects the current delegation supplied as an
295300
-- argument, because in ledger rules we already have it readily available.
@@ -299,23 +304,27 @@ processDelegationInternal ::
299304
Bool ->
300305
-- | Delegator
301306
Credential 'Staking ->
302-
-- | Current delegatee for the above stake credential that needs to be cleaned up.
303-
Maybe Delegatee ->
307+
-- | Account state for the above stake credential
308+
Maybe (AccountState era) ->
304309
-- | New delegatee
305310
Delegatee ->
306311
CertState era ->
307312
CertState era
308-
processDelegationInternal preserveIncorrectDelegation stakeCred mCurDelegatee newDelegatee =
313+
processDelegationInternal preserveIncorrectDelegation stakeCred mAccountState newDelegatee =
309314
case newDelegatee of
310315
DelegStake sPool -> delegStake sPool
311316
DelegVote dRep -> delegVote dRep
312317
DelegStakeVote sPool dRep -> delegVote dRep . delegStake sPool
313318
where
319+
mCurDelegatee = mAccountState >>= accountStateDelegatee
314320
delegStake stakePool cState =
315321
cState
316322
& certDStateL . accountsL
317323
%~ adjustAccountState (stakePoolDelegationAccountStateL ?~ stakePool) stakeCred
318-
& certPStateL %~ adjustPState stakePool
324+
& maybe
325+
(certPStateL . psStakePoolsL %~ Map.adjust (spsDelegatorsL %~ Set.insert stakeCred) stakePool)
326+
(\accountState -> certPStateL %~ unDelegReDelegStakePool stakeCred accountState (Just stakePool))
327+
mAccountState
319328
delegVote dRep cState =
320329
let cState' =
321330
cState
@@ -331,26 +340,6 @@ processDelegationInternal preserveIncorrectDelegation stakeCred mCurDelegatee ne
331340
let dRepState' = dRepState {drepDelegs = Set.insert stakeCred (drepDelegs dRepState)}
332341
in cState' & certVStateL . vsDRepsL .~ Map.insert targetDRep dRepState' dReps
333342
_ -> cState'
334-
adjustPState newPool =
335-
(psStakePoolsL %~ Map.adjust (spsDelegatorsL %~ Set.insert stakeCred) newPool)
336-
. unDelegStakePool stakeCred mCurDelegatee (Just newPool)
337-
338-
unDelegStakePool ::
339-
Credential 'Staking ->
340-
Maybe Delegatee ->
341-
Maybe (KeyHash 'StakePool) ->
342-
PState era ->
343-
PState era
344-
unDelegStakePool stakeCred mCurDelegatee mNewPool =
345-
maybe
346-
id
347-
(\oldPool -> psStakePoolsL %~ Map.adjust (spsDelegatorsL %~ Set.delete stakeCred) oldPool)
348-
(mCurDelegatee >>= stakePoolToUnDeleg)
349-
where
350-
stakePoolToUnDeleg = \case
351-
DelegStake oldPool | Just oldPool /= mNewPool -> Just oldPool
352-
DelegStakeVote oldPool _ | Just oldPool /= mNewPool -> Just oldPool
353-
_ -> Nothing
354343

355344
unDelegDRep ::
356345
Credential 'Staking ->

eras/shelley/impl/src/Cardano/Ledger/Shelley/Rules/Deleg.hs

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ delegationTransition = do
282282
certState
283283
& certDStateL . accountsL .~ accounts
284284
& certPStateL
285-
%~ unDelegStakePool cred (accountState ^. stakePoolDelegationAccountStateL) Nothing
285+
%~ unDelegReDelegStakePool cred accountState Nothing
286286
DelegStakeTxCert cred stakePool -> do
287287
-- note that pattern match is used instead of cwitness and dpool, as in the spec
288288
-- (hk ∈ dom (rewards ds))
@@ -294,10 +294,7 @@ delegationTransition = do
294294
pure $
295295
certState
296296
& certDStateL . accountsL %~ adjustAccountState (stakePoolDelegationAccountStateL ?~ stakePool) cred
297-
& certPStateL %~ \ps ->
298-
ps
299-
& unDelegStakePool cred (accountState ^. stakePoolDelegationAccountStateL) (Just stakePool)
300-
& psStakePoolsL %~ Map.adjust (spsDelegatorsL %~ Set.insert cred) stakePool
297+
& certPStateL %~ unDelegReDelegStakePool cred accountState (Just stakePool)
301298
GenesisDelegTxCert gkh vkh vrf -> do
302299
sp <- liftSTS $ asks stabilityWindow
303300
-- note that pattern match is used instead of genesisDeleg, as in the spec
@@ -420,19 +417,3 @@ updateReservesAndTreasury targetPot combinedMap available certState = do
420417
case targetPot of
421418
ReservesMIR -> certState & certDStateL . dsIRewardsL . iRReservesL .~ combinedMap
422419
TreasuryMIR -> certState & certDStateL . dsIRewardsL . iRTreasuryL .~ combinedMap
423-
424-
unDelegStakePool ::
425-
Credential 'Staking ->
426-
Maybe (KeyHash 'StakePool) ->
427-
Maybe (KeyHash 'StakePool) ->
428-
PState era ->
429-
PState era
430-
unDelegStakePool stakeCred mCurStakePool mNewPool =
431-
maybe
432-
id
433-
(\oldPool -> psStakePoolsL %~ Map.adjust (spsDelegatorsL %~ Set.delete stakeCred) oldPool)
434-
(mCurStakePool >>= stakePoolToUnDeleg)
435-
where
436-
stakePoolToUnDeleg oldPool
437-
| Just oldPool /= mNewPool = Just oldPool
438-
| otherwise = Nothing

libs/cardano-ledger-core/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## 1.19.0.0
44

5+
* Add `unDelegReDelegStakePool` to `CertState` module
56
* Add `iRReservesL`, `iRTreasuryL`, `iRDeltaReservesL`, `iRDeltaTreasuryL`
67
* Add `spsDelegators` field to `StakePool`
78
* Add `spsDelegatorsL`

libs/cardano-ledger-core/src/Cardano/Ledger/State/CertState.hs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ module Cardano.Ledger.State.CertState (
3434
lookupRewardDState,
3535
Obligations (..),
3636
sumObligation,
37+
unDelegReDelegStakePool,
3738
-- Lenses
3839
iRReservesL,
3940
dsIRewardsL,
@@ -80,7 +81,7 @@ import Cardano.Ledger.DRep (DRep (..), DRepState (..))
8081
import Cardano.Ledger.Hashes (GenDelegPair (..), GenDelegs (..))
8182
import Cardano.Ledger.Slot (EpochNo (..), SlotNo (..))
8283
import Cardano.Ledger.State.Account
83-
import Cardano.Ledger.State.StakePool (StakePoolState (..))
84+
import Cardano.Ledger.State.StakePool (StakePoolState (..), spsDelegatorsL)
8485
import Control.DeepSeq (NFData (..))
8586
import Control.Monad.Trans
8687
import Data.Aeson (ToJSON (..), object, (.=))
@@ -89,6 +90,7 @@ import qualified Data.Foldable as F
8990
import Data.Kind (Type)
9091
import Data.Map.Strict (Map)
9192
import qualified Data.Map.Strict as Map
93+
import Data.Maybe (fromMaybe)
9294
import qualified Data.Set as Set
9395
import Data.Word (Word64)
9496
import GHC.Generics (Generic)
@@ -273,6 +275,30 @@ instance ToKeyValuePairs (PState era) where
273275
, "retiring" .= psRetiring
274276
]
275277

278+
-- | Reverses stake pool delegation.
279+
-- To be called when a stake credential is unregistered or its delegation target changes.
280+
-- If the new delegation matches the previous one, this is a noop.
281+
unDelegReDelegStakePool ::
282+
EraAccounts era =>
283+
Credential 'Staking ->
284+
-- | Account that is losing its current delegation and/or acquiring a new one
285+
AccountState era ->
286+
-- | Optional new delegation target. Use 'Nothing' when the stake credential unregisters.
287+
Maybe (KeyHash 'StakePool) ->
288+
PState era ->
289+
PState era
290+
unDelegReDelegStakePool stakeCred accountState mNewStakePool =
291+
fromMaybe (psStakePoolsL %~ addNewDelegation) $ do
292+
curStakePool <- accountState ^. stakePoolDelegationAccountStateL
293+
pure $
294+
-- no need to update the set of delegations if the delegation is unchanged
295+
if Just curStakePool == mNewStakePool
296+
then id
297+
else
298+
psStakePoolsL %~ addNewDelegation . Map.adjust (spsDelegatorsL %~ Set.delete stakeCred) curStakePool
299+
where
300+
addNewDelegation = maybe id (Map.adjust (spsDelegatorsL %~ Set.insert stakeCred)) mNewStakePool
301+
276302
data CommitteeAuthorization
277303
= -- | Member authorized with a Hot credential acting on behalf of their Cold credential
278304
CommitteeHotCredential !(Credential 'HotCommitteeRole)

0 commit comments

Comments
 (0)