@@ -21,16 +21,52 @@ import Control.Exception
2121import Data.List.NonEmpty (NonEmpty (.. ))
2222import qualified Data.List.NonEmpty as NonEmpty
2323import Data.Maybe (catMaybes )
24+ import Data.Time.Clock (DiffTime )
25+ import Data.Word (Word64 )
2426import Ouroboros.Consensus.Config (TopLevelConfig )
2527import Ouroboros.Consensus.Config.SecurityParam
2628
27- -- | An issue found in the 'TopLevelConfig' for a block . See 'displayException'
29+ -- | An issue found in the consensus configuration . See 'displayException'
2830-- for human-readable descriptions of each of these cases, especially when
2931-- presenting these to users.
3032data SanityCheckIssue
3133 = -- | Configuration contains multiple security parameters. This may cause
3234 -- strange behaviour around era boundaries.
3335 InconsistentSecurityParam (NonEmpty SecurityParam )
36+ | -- | The configured 'minimumDelay' in 'SnapshotDelayRange' is greater than
37+ -- 'maximumDelay'. The random snapshot delay will be sampled from an
38+ -- inverted range, which is almost certainly a misconfiguration.
39+ SnapshotDelayRangeInverted
40+ -- | The configured minimumDelay (the larger value)
41+ ! DiffTime
42+ -- | The configured maximumDelay (the smaller value)
43+ ! DiffTime
44+ | -- | The configured 'minimumDelay' in 'SnapshotDelayRange' is negative.
45+ -- A negative delay has no meaningful interpretation.
46+ SnapshotDelayRangeNegativeMinimum
47+ -- | The negative minimumDelay
48+ ! DiffTime
49+ | -- | The configured 'sfaRateLimit' is non-positive, which disables snapshot
50+ -- rate limiting entirely. Without a rate limit, snapshots may be taken
51+ -- very frequently during bulk sync, causing excessive disk I/O.
52+ SnapshotRateLimitDisabled
53+ | -- | The configured 'sfaRateLimit' exceeds 24 hours. At steady state, the
54+ -- node may go more than a day between snapshots, significantly increasing
55+ -- replay time after an unclean restart.
56+ SnapshotRateLimitSuspiciouslyLarge
57+ -- | The configured rate limit
58+ ! DiffTime
59+ | -- | The configured number of on-disk snapshots to keep is zero. Snapshots
60+ -- will be written to disk and then immediately deleted, leaving nothing
61+ -- for crash recovery. The node will have to replay from genesis on every
62+ -- unclean restart.
63+ SnapshotNumZero
64+ | -- | The configured snapshot interval does not divide 432000 (the Cardano
65+ -- mainnet epoch length in slots). Snapshots will not land on epoch
66+ -- boundaries, breaking Mithril compatibility.
67+ SnapshotIntervalNotDivisorOfEpoch
68+ -- | The configured interval in slots
69+ ! Word64
3470 deriving (Show , Eq )
3571
3672instance Exception SanityCheckIssue where
@@ -42,6 +78,61 @@ instance Exception SanityCheckIssue where
4278 , " eras of a HardForkBlock: "
4379 , show (NonEmpty. toList ks)
4480 ]
81+ SnapshotDelayRangeInverted mn mx ->
82+ mconcat
83+ [ " SnapshotDelayRangeInverted: "
84+ , " The configured snapshot delay range has minimumDelay ("
85+ , show mn
86+ , " ) greater than maximumDelay ("
87+ , show mx
88+ , " ). The random snapshot delay will be sampled from an inverted range. "
89+ , " Please ensure minimumDelay <= maximumDelay in sfaDelaySnapshotRange."
90+ ]
91+ SnapshotDelayRangeNegativeMinimum mn ->
92+ mconcat
93+ [ " SnapshotDelayRangeNegativeMinimum: "
94+ , " The configured snapshot delay range has a negative minimumDelay: "
95+ , show mn
96+ , " . A negative delay has no meaningful interpretation. "
97+ , " Please set minimumDelay to a non-negative value in sfaDelaySnapshotRange."
98+ ]
99+ SnapshotRateLimitDisabled ->
100+ mconcat
101+ [ " SnapshotRateLimitDisabled: "
102+ , " The configured sfaRateLimit is non-positive, which disables snapshot "
103+ , " rate limiting entirely. Without a rate limit, snapshots may be taken "
104+ , " very frequently during bulk sync, causing excessive disk I/O. "
105+ , " The default rate limit is 10 minutes."
106+ ]
107+ SnapshotRateLimitSuspiciouslyLarge rl ->
108+ mconcat
109+ [ " SnapshotRateLimitSuspiciouslyLarge: "
110+ , " The configured sfaRateLimit ("
111+ , show rl
112+ , " ) exceeds 24 hours. At steady state, the node may go more than a day "
113+ , " between snapshots, significantly increasing replay time after an "
114+ , " unclean restart. The default rate limit is 10 minutes."
115+ ]
116+ SnapshotNumZero ->
117+ mconcat
118+ [ " SnapshotNumZero: "
119+ , " The configured number of on-disk snapshots to keep (spaNum) is 0. "
120+ , " Snapshots will be written to disk and immediately deleted, leaving "
121+ , " nothing for crash recovery. The node will have to replay the chain "
122+ , " from genesis on every unclean restart. "
123+ , " Consider setting spaNum to at least 2 (the default)."
124+ ]
125+ SnapshotIntervalNotDivisorOfEpoch interval ->
126+ mconcat
127+ [ " SnapshotIntervalNotDivisorOfEpoch: "
128+ , " The configured sfaInterval ("
129+ , show interval
130+ , " slots) does not evenly divide the Cardano mainnet epoch length "
131+ , " (432000 slots). Snapshots will not consistently land on epoch "
132+ , " boundaries, which breaks Mithril compatibility. "
133+ , " Consider using an interval that divides 432000 evenly, "
134+ , " such as 4320 (the default, = 2k for k=2160)."
135+ ]
45136
46137-- | 'BlockSupportsSanityCheck' provides evidence that a block can be sanity
47138-- checked for common issues on node startup. 'sanityCheckConfig', which runs
0 commit comments