Skip to content

Commit aaad29d

Browse files
committed
Find epochs that have missing epoch_stake entries
Caused by bug #1678
1 parent b8748fb commit aaad29d

File tree

5 files changed

+101
-3
lines changed

5 files changed

+101
-3
lines changed

cardano-db-sync/src/Cardano/DbSync/Default.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ insertBlock syncEnv cblk applyRes firstAfterRollback tookSnapshot = do
157157
let !details = apSlotDetails applyResult
158158
let !withinTwoMin = isWithinTwoMin details
159159
let !withinHalfHour = isWithinHalfHour details
160-
insertNewEpochLedgerEvents syncEnv (sdEpochNo details) (apEvents applyResult)
160+
insertNewEpochLedgerEvents syncEnv applyResult (sdEpochNo details) (apEvents applyResult)
161161

162162
let isNewEpochEvent = hasNewEpochEvent (apEvents applyResult)
163163
let isStartEventOrRollback = hasEpochStartEvent (apEvents applyResult) || firstAfterRollback

cardano-db-sync/src/Cardano/DbSync/Era/Shelley/Generic/StakeDist.hs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module Cardano.DbSync.Era.Shelley.Generic.StakeDist (
1212
StakeSlice (..),
1313
getSecurityParameter,
1414
getStakeSlice,
15+
countEpochStake,
1516
getPoolDistr,
1617
) where
1718

@@ -175,6 +176,46 @@ genericStakeSlice pInfo epochBlockNo lstate isMigration
175176
VMap.mapMaybe id $
176177
VMap.mapWithKey (\a p -> (,p) <$> lookupStake a) delegationsSliced
177178

179+
countEpochStake ::
180+
ExtLedgerState CardanoBlock mk ->
181+
Maybe (Word64, EpochNo)
182+
countEpochStake els =
183+
case ledgerState els of
184+
LedgerStateByron _ -> Nothing
185+
LedgerStateShelley sls -> genericCountEpochStake sls
186+
LedgerStateAllegra als -> genericCountEpochStake als
187+
LedgerStateMary mls -> genericCountEpochStake mls
188+
LedgerStateAlonzo als -> genericCountEpochStake als
189+
LedgerStateBabbage bls -> genericCountEpochStake bls
190+
LedgerStateConway cls -> genericCountEpochStake cls
191+
LedgerStateDijkstra dls -> genericCountEpochStake dls
192+
193+
genericCountEpochStake ::
194+
LedgerState (ShelleyBlock p era) mk ->
195+
Maybe (Word64, EpochNo)
196+
genericCountEpochStake lstate =
197+
Just (delegationsLen, epoch)
198+
where
199+
epoch :: EpochNo
200+
epoch = EpochNo $ 1 + unEpochNo (Shelley.nesEL (Consensus.shelleyLedgerState lstate))
201+
202+
stakeSnapshot :: Ledger.SnapShot
203+
stakeSnapshot =
204+
Ledger.ssStakeMark . Shelley.esSnapshots . Shelley.nesEs $
205+
Consensus.shelleyLedgerState lstate
206+
207+
delegations :: VMap VB VB (Credential 'Staking) (KeyHash 'StakePool)
208+
delegations = Ledger.ssDelegations stakeSnapshot
209+
210+
delegationsLen :: Word64
211+
delegationsLen = fromIntegral $ VMap.size $ VMap.filter (\k _ -> hasStake k) delegations
212+
213+
stakes :: VMap VB VP (Credential 'Staking) (Ledger.CompactForm Coin)
214+
stakes = Ledger.unStake $ Ledger.ssStake stakeSnapshot
215+
216+
hasStake :: Credential 'Staking -> Bool
217+
hasStake cred = isJust (VMap.lookup cred stakes)
218+
178219
getPoolDistr ::
179220
ExtLedgerState CardanoBlock mk ->
180221
Maybe (Map PoolKeyHash (Coin, Word64), Map PoolKeyHash Natural)

cardano-db-sync/src/Cardano/DbSync/Era/Universal/Insert/LedgerEvent.hs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import qualified Cardano.DbSync.Era.Shelley.Generic as Generic
2525
import Cardano.DbSync.Era.Universal.Adjust (adjustEpochRewards)
2626
import Cardano.DbSync.Era.Universal.Epoch (insertPoolDepositRefunds, insertProposalRefunds, insertRewardRests, insertRewards)
2727
import Cardano.DbSync.Era.Universal.Insert.GovAction
28-
import Cardano.DbSync.Era.Universal.Validate (validateEpochRewards)
28+
import Cardano.DbSync.Era.Universal.Validate (validateEpochStake, validateEpochRewards)
2929
import Cardano.DbSync.Ledger.Event
3030
import Cardano.DbSync.Types
3131

@@ -38,16 +38,18 @@ import qualified Data.Set as Set
3838
import qualified Data.Text as Text
3939
import Data.Time (UTCTime, diffUTCTime, getCurrentTime)
4040
import Text.Printf (printf)
41+
import Cardano.DbSync.Ledger.Types
4142

4243
--------------------------------------------------------------------------------------------
4344
-- Insert LedgerEvents
4445
--------------------------------------------------------------------------------------------
4546
insertNewEpochLedgerEvents ::
4647
SyncEnv ->
48+
ApplyResult ->
4749
EpochNo ->
4850
[LedgerEvent] ->
4951
ExceptT SyncNodeError DB.DbM ()
50-
insertNewEpochLedgerEvents syncEnv currentEpochNo@(EpochNo curEpoch) =
52+
insertNewEpochLedgerEvents syncEnv applyRes currentEpochNo@(EpochNo curEpoch) =
5153
mapM_ handler
5254
where
5355
metricSetters = envMetricSetters syncEnv
@@ -72,6 +74,7 @@ insertNewEpochLedgerEvents syncEnv currentEpochNo@(EpochNo curEpoch) =
7274
handler ev =
7375
case ev of
7476
LedgerNewEpoch en ss -> do
77+
validateEpochStake tracer applyRes
7578
databaseCacheSize <- lift DB.queryStatementCacheSize
7679
liftIO . logInfo tracer $ "Database Statement Cache size is " <> textShow databaseCacheSize
7780
currentTime <- liftIO getCurrentTime

cardano-db-sync/src/Cardano/DbSync/Era/Universal/Validate.hs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
{-# LANGUAGE NoImplicitPrelude #-}
66

77
module Cardano.DbSync.Era.Universal.Validate (
8+
validateEpochStake,
89
validateEpochRewards,
910
) where
1011

@@ -24,6 +25,36 @@ import qualified Cardano.DbSync.Era.Shelley.Generic as Generic
2425
import Cardano.DbSync.Error (SyncNodeError)
2526
import Cardano.DbSync.Ledger.Event
2627
import Cardano.DbSync.Types
28+
import Cardano.DbSync.Ledger.Types
29+
import qualified Data.Strict.Maybe as Strict
30+
31+
validateEpochStake ::
32+
Trace IO Text ->
33+
ApplyResult -> ExceptT SyncNodeError DB.DbM ()
34+
validateEpochStake tracer applyRes = case apOldLedger applyRes of
35+
Strict.Just lstate | Just (expectedCount, epoch) <- Generic.countEpochStake (clsState lstate) -> do
36+
actualCount <- lift $ DB.queryNormalEpochStakeCount (unEpochNo epoch)
37+
if actualCount /= expectedCount then
38+
liftIO
39+
. logWarning tracer
40+
$ mconcat
41+
[ "validateEpochStake: epoch stake in epoch "
42+
, textShow (unEpochNo epoch)
43+
, " expected total of "
44+
, textShow expectedCount
45+
, " but got "
46+
, textShow actualCount
47+
]
48+
else
49+
liftIO $ logInfo tracer
50+
$ mconcat
51+
[ "Validate Epoch Stake: total entries in epoch "
52+
, textShow (unEpochNo epoch)
53+
, " are "
54+
, textShow actualCount
55+
]
56+
_ -> pure ()
57+
2758

2859
validateEpochRewards ::
2960
Trace IO Text ->

cardano-db/src/Cardano/Db/Statement/StakeDelegation.hs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,29 @@ queryNormalEpochRewardCount epochNum =
216216
runSession mkDbCallStack $
217217
HsqlSes.statement epochNum queryNormalEpochRewardCountStmt
218218

219+
-- | QUERY ---------------------------------------------------------------------
220+
queryNormalEpochStakeCountStmt :: HsqlStmt.Statement Word64 Word64
221+
queryNormalEpochStakeCountStmt =
222+
HsqlStmt.Statement sql encoder decoder True
223+
where
224+
sql =
225+
TextEnc.encodeUtf8 $
226+
Text.concat
227+
[ "SELECT COUNT(*)::bigint"
228+
, " FROM epoch_stake"
229+
, " WHERE epoch_no = $1"
230+
]
231+
232+
encoder = HsqlE.param (HsqlE.nonNullable $ fromIntegral >$< HsqlE.int8)
233+
decoder =
234+
HsqlD.singleRow $
235+
fromIntegral <$> HsqlD.column (HsqlD.nonNullable HsqlD.int8)
236+
237+
queryNormalEpochStakeCount :: Word64 -> DbM Word64
238+
queryNormalEpochStakeCount epochNum =
239+
runSession mkDbCallStack $
240+
HsqlSes.statement epochNum queryNormalEpochStakeCountStmt
241+
219242
--------------------------------------------------------------------------------
220243
queryRewardCount :: DbM Word64
221244
queryRewardCount =

0 commit comments

Comments
 (0)