2
2
3
3
module Cardano.DbSync.Ledger.Async where
4
4
5
+ import Cardano.DbSync.Era.Shelley.Generic.Rewards as Generic
6
+ import Cardano.DbSync.Ledger.Event
5
7
import Cardano.DbSync.Ledger.Types
6
- import Cardano.Ledger.BaseTypes (EpochNo )
8
+ import Cardano.DbSync.Types
9
+ import Cardano.Ledger.BaseTypes
7
10
import Cardano.Ledger.Crypto (StandardCrypto )
8
11
import qualified Cardano.Ledger.EpochBoundary as Ledger
12
+ import qualified Cardano.Ledger.Rewards as Ledger
13
+ import Cardano.Ledger.Shelley.RewardUpdate as Ledger
9
14
import Control.Concurrent.Class.MonadSTM.Strict
10
15
import qualified Control.Concurrent.STM.TBQueue as TBQ
16
+ import Control.Monad.Extra (whenJust )
17
+ import Data.Map (Map )
18
+ import Data.Set (Set )
19
+ import Data.Word (Word64 )
20
+
21
+ --------------------------------------------------------------------------------
22
+ -- EpochStake
23
+ --------------------------------------------------------------------------------
11
24
12
25
newEpochStakeChannels :: IO EpochStakeChannels
13
26
newEpochStakeChannels =
@@ -18,9 +31,9 @@ newEpochStakeChannels =
18
31
<*> newTVarIO Nothing
19
32
20
33
-- To be used by the main thread
21
- ensureEpochDone :: EpochStakeChannels -> EpochNo -> Ledger. SnapShot StandardCrypto -> IO ()
22
- ensureEpochDone sQueue epoch snapshot = atomically $ do
23
- mLastEpochDone <- waitFinished sQueue
34
+ ensureStakeDone :: EpochStakeChannels -> EpochNo -> Ledger. SnapShot StandardCrypto -> IO ()
35
+ ensureStakeDone sQueue epoch snapshot = atomically $ do
36
+ mLastEpochDone <- waitStakeFinished sQueue
24
37
case mLastEpochDone of
25
38
Just lastEpochDone | lastEpochDone == epoch -> pure ()
26
39
_ -> do
@@ -29,8 +42,8 @@ ensureEpochDone sQueue epoch snapshot = atomically $ do
29
42
retry
30
43
31
44
-- To be used by the main thread
32
- waitFinished :: EpochStakeChannels -> STM IO (Maybe EpochNo )
33
- waitFinished sQueue = do
45
+ waitStakeFinished :: EpochStakeChannels -> STM IO (Maybe EpochNo )
46
+ waitStakeFinished sQueue = do
34
47
stakeThreadState <- readTVar (epochResult sQueue)
35
48
case stakeThreadState of
36
49
Just (lastEpoch, Done ) -> pure $ Just lastEpoch -- Normal case
@@ -42,3 +55,74 @@ writeEpochStakeAction :: EpochStakeChannels -> EpochNo -> Ledger.SnapShot Standa
42
55
writeEpochStakeAction sQueue epoch snapShot checkFirst = do
43
56
TBQ. writeTBQueue (estakeQueue sQueue) $ EpochStakeDBAction epoch snapShot checkFirst
44
57
writeTVar (epochResult sQueue) $ Just (epoch, Running )
58
+
59
+ --------------------------------------------------------------------------------
60
+ -- Rewards
61
+ --------------------------------------------------------------------------------
62
+
63
+ newRewardsChannels :: IO RewardsChannels
64
+ newRewardsChannels =
65
+ RewardsChannels
66
+ <$> TBQ. newTBQueueIO 5
67
+ <*> newTVarIO Nothing
68
+
69
+ -- TODO: add a boolean flag that shows the start of the epoch, so that 'isNewEpoch' is more reliable
70
+ asyncWriteRewards :: HasLedgerEnv -> CardanoLedgerState -> EpochNo -> Bool -> [LedgerEvent ] -> IO ()
71
+ asyncWriteRewards env newState currentEpochNo isNewEpoch rewardEventsEB = do
72
+ rewState <- atomically $ readTVar $ rewardsResult rc
73
+ if isNewEpoch
74
+ then do
75
+ case rewState of
76
+ Just (e', RewRunning ) | e' == currentEpochNo -> do
77
+ waitRewardUntil rc (e', RewDone )
78
+ _ -> do
79
+ ensureRewardsDone rc currentEpochNo (findTotal rewardEventsEB)
80
+ waitEBRewardsAction rc currentEpochNo rewardEventsEB
81
+ else do
82
+ case rewState of {}
83
+ whenJust (Generic. getRewardsUpdate (getTopLevelconfigHasLedger env) (clsState newState)) $ \ ru -> do
84
+ atomically $ writeRewardsAction rc currentEpochNo currentEpochNo False (Ledger. rs ru) -- (e-1) (e+1)
85
+ where
86
+ rc = leRewardsChans env
87
+
88
+ _subFromCurrentEpoch :: Word64 -> EpochNo
89
+ _subFromCurrentEpoch m =
90
+ if unEpochNo currentEpochNo >= m
91
+ then EpochNo $ unEpochNo currentEpochNo - m
92
+ else EpochNo 0
93
+
94
+ findTotal :: [LedgerEvent ] -> Maybe (Map StakeCred (Set (Ledger. Reward StandardCrypto )))
95
+ findTotal [] = Nothing
96
+ findTotal (LedgerTotalRewards _ mp : _) = Just mp
97
+ findTotal (_ : rest) = findTotal rest
98
+
99
+ -- To be used by the main thread
100
+ ensureRewardsDone :: RewardsChannels -> EpochNo -> Maybe (Map StakeCred (Set (Ledger. Reward StandardCrypto ))) -> IO ()
101
+ ensureRewardsDone rc epoch mmp = do
102
+ whenJust mmp $ \ mp -> do
103
+ atomically $ writeRewardsAction rc epoch epoch True mp -- e-2 e-1
104
+ waitRewardUntil rc (epoch, RewDone )
105
+
106
+ waitEBRewardsAction :: RewardsChannels -> EpochNo -> [LedgerEvent ] -> IO ()
107
+ waitEBRewardsAction rc epoch les = do
108
+ atomically $ do
109
+ TBQ. writeTBQueue (rQueue rc) $ RewardsEpochBoundary epoch les
110
+ writeTVar (rewardsResult rc) $ Just (epoch, RewEBRunning )
111
+ waitRewardUntil rc (epoch, RewEBDone )
112
+
113
+ -- To be used by the main thread
114
+ writeRewardsAction :: RewardsChannels -> EpochNo -> EpochNo -> Bool -> Map StakeCred (Set (Ledger. Reward StandardCrypto )) -> STM IO ()
115
+ writeRewardsAction rc epoch epoch' checkFirst mp = do
116
+ TBQ. writeTBQueue (rQueue rc) $ RewardsDBAction epoch epoch' mp checkFirst
117
+ writeTVar (rewardsResult rc) $ Just (epoch, RewRunning )
118
+
119
+ waitRewardUntil :: RewardsChannels -> (EpochNo , EpochRewardState ) -> IO ()
120
+ waitRewardUntil rc st = waitRewardUntilPred rc (== st)
121
+
122
+ -- blocks until the reward result satisfies a specific predicate.
123
+ waitRewardUntilPred :: RewardsChannels -> ((EpochNo , EpochRewardState ) -> Bool ) -> IO ()
124
+ waitRewardUntilPred rc prd = atomically $ do
125
+ rewardsThreadState <- readTVar (rewardsResult rc)
126
+ case rewardsThreadState of
127
+ Just st | prd st -> pure ()
128
+ _ -> retry
0 commit comments