diff --git a/eras/shelley/impl/src/Cardano/Ledger/Shelley/LedgerState.hs b/eras/shelley/impl/src/Cardano/Ledger/Shelley/LedgerState.hs index a045b66519d..7d8fc28ab3c 100644 --- a/eras/shelley/impl/src/Cardano/Ledger/Shelley/LedgerState.hs +++ b/eras/shelley/impl/src/Cardano/Ledger/Shelley/LedgerState.hs @@ -77,6 +77,7 @@ module Cardano.Ledger.Shelley.LedgerState updateStakeDistribution, applyRUpd, applyRUpd', + filterAllRewards, createRUpd, completeRupd, startStep, @@ -1189,17 +1190,12 @@ applyRUpd' :: (EpochState era, Map (Credential 'Staking (Crypto era)) (Set (Reward (Crypto era)))) applyRUpd' ru - (EpochState as ss ls pr pp _nm) = (EpochState as' ss ls' pr pp nm', registered) + es@(EpochState as ss ls pr pp _nm) = (EpochState as' ss ls' pr pp nm', registered) where utxoState_ = _utxoState ls delegState = _delegationState ls dState = _dstate delegState - (regRU, unregRU) = - Map.partitionWithKey - (\k _ -> eval (k ∈ dom (rewards dState))) - (rs ru) - totalUnregistered = fold $ aggregateRewards pr unregRU - registered = filterRewards pr regRU + (registered, totalUnregistered) = filterAllRewards (rs ru) es registeredAggregated = aggregateRewards pp registered as' = as @@ -1220,6 +1216,24 @@ applyRUpd' } nm' = nonMyopic ru +filterAllRewards :: + ( HasField "_protocolVersion" (Core.PParams era) ProtVer + ) => + Map (Credential 'Staking (Crypto era)) (Set (Reward (Crypto era))) -> + EpochState era -> + (Map (Credential 'Staking (Crypto era)) (Set (Reward (Crypto era))), Coin) +filterAllRewards rs' (EpochState _as _ss ls pr _pp _nm) = + (registered, totalUnregistered) + where + delegState = _delegationState ls + dState = _dstate delegState + (regRU, unregRU) = + Map.partitionWithKey + (\k _ -> eval (k ∈ dom (rewards dState))) + rs' + totalUnregistered = fold $ aggregateRewards pr unregRU + registered = filterRewards pr regRU + decayFactor :: Float decayFactor = 0.9 diff --git a/eras/shelley/impl/src/Cardano/Ledger/Shelley/Rules/NewEpoch.hs b/eras/shelley/impl/src/Cardano/Ledger/Shelley/Rules/NewEpoch.hs index f6b95ed9e71..bc112444523 100644 --- a/eras/shelley/impl/src/Cardano/Ledger/Shelley/Rules/NewEpoch.hs +++ b/eras/shelley/impl/src/Cardano/Ledger/Shelley/Rules/NewEpoch.hs @@ -156,10 +156,10 @@ newEpochTransition = do let updateRewards ru'@(RewardUpdate dt dr rs_ df _) = do let totRs = sumRewards (esPrevPp es) rs_ Val.isZero (dt <> (dr <> toDeltaCoin totRs <> df)) ?! CorruptRewardUpdate ru' - let (es', _regRU) = applyRUpd' ru' es + let (es', regRU) = applyRUpd' ru' es -- This event (which is only generated once per epoch) must be generated even if the -- map is empty (db-sync depends on it). - tellEvent (TotalRewardEvent e rs_) + tellEvent $ TotalRewardEvent e regRU pure es' es' <- case ru of SNothing -> pure es diff --git a/eras/shelley/test-suite/test/Test/Cardano/Ledger/Shelley/Rewards.hs b/eras/shelley/test-suite/test/Test/Cardano/Ledger/Shelley/Rewards.hs index d88d78409b1..f185e29e608 100644 --- a/eras/shelley/test-suite/test/Test/Cardano/Ledger/Shelley/Rewards.hs +++ b/eras/shelley/test-suite/test/Test/Cardano/Ledger/Shelley/Rewards.hs @@ -74,6 +74,7 @@ import Cardano.Ledger.Shelley.LedgerState circulation, completeRupd, createRUpd, + filterAllRewards, rewards, updateNonMyopic, ) @@ -104,7 +105,7 @@ import Cardano.Ledger.Shelley.Rewards mkApparentPerformance, mkPoolRewardInfo, ) -import Cardano.Ledger.Shelley.Rules.NewEpoch (NewEpochEvent (TotalRewardEvent)) +import Cardano.Ledger.Shelley.Rules.NewEpoch (NewEpochEvent (DeltaRewardEvent, TotalRewardEvent)) import Cardano.Ledger.Shelley.Rules.Rupd (RupdEvent (..)) import qualified Cardano.Ledger.Shelley.Rules.Tick as Tick import Cardano.Ledger.Shelley.TxBody (PoolParams (..), RewardAcnt (..)) @@ -750,10 +751,11 @@ newEpochEventsProp tracelen propf = withMaxSuccess 10 $ Just SourceSignalTarget {target} -> propf (concat (runShelleyBase $ getEvents tr)) (chainNes target) _ -> True === True -aggDeltaRewardEvents :: [ChainEvent C] -> Map (Credential 'Staking (Crypto C)) (Set (Reward (Crypto C))) -aggDeltaRewardEvents events = foldl' accum Map.empty events +aggIncrementalRewardEvents :: [ChainEvent C] -> Map (Credential 'Staking (Crypto C)) (Set (Reward (Crypto C))) +aggIncrementalRewardEvents events = foldl' accum Map.empty events where accum ans (TickEvent (Tick.RupdEvent (RupdEvent _ m))) = Map.unionWith Set.union m ans + accum ans (TickEvent (Tick.NewEpochEvent (DeltaRewardEvent (RupdEvent _ m)))) = Map.unionWith Set.union m ans accum ans _ = ans getMostRecentTotalRewardEvent :: [ChainEvent C] -> Map (Credential 'Staking (Crypto C)) (Set (Reward (Crypto C))) @@ -770,21 +772,22 @@ eventsMirrorRewards :: [ChainEvent C] -> NewEpochState C -> Property eventsMirrorRewards events nes = same eventRew compRew where (compRew, eventRew) = - case (nesRu nes) of - SNothing -> (total, aggevent) + case nesRu nes of + SNothing -> (total, aggFilteredEvent) SJust pulser -> - ( Map.unionWith (Set.union) (rs completed) total, - Map.unionWith (Set.union) lastevent aggevent + ( Map.unionWith Set.union (rs completed) total, + Map.unionWith Set.union lastevent aggevent ) where (completed, lastevent) = complete pulser total = getMostRecentTotalRewardEvent events - aggevent = aggDeltaRewardEvents events + aggevent = aggIncrementalRewardEvents events + (aggFilteredEvent, _) = filterAllRewards aggevent (nesEs nes) same x y = withMaxSuccess 1 $ counterexample message (x === y) where message = ( "events don't mirror rewards " - ++ tersemapdiffs "Map differences: aggregated events on the left, computed on the right." x y + ++ tersemapdiffs "Map differences: aggregated filtered events on the left, computed on the right." x y ) ppAgg :: Map (Credential 'Staking (Crypto C)) (Set (Reward (Crypto C))) -> PDoc