Skip to content

Commit 96f28fb

Browse files
committed
Remove LedgerDbPruneKeeping
It was already superseded in the most important places due to `LedgerDbPruneBeforeSlot`. Its remaining use cases are non-essential: - Replay on startup. In this case, we never roll back, so not maintaining k states is actually an optimization here. We can also remove the now-redundant `InitDB.pruneDb` function. - Internal functions used for db-analyser. Here, we can just as well use `LedgerDbPruneAll` (which is used by `pruneToImmTipOnly`) as we never need to roll back. - Testing. In particular, we remove some DbChangelog tests that previously ensured that only at most @k@ states are kept. This is now no longer true; that property is instead enforced by the LedgerDB built on top of the DbChangelog. A follow-up commit in this PR enriches the LedgerDB state machine test to make sure that the public API functions behave appropriately, ensuring that we don't lose test coverage (and also testing V2, which previously didn't have any such tests).
1 parent d278b49 commit 96f28fb

File tree

7 files changed

+69
-179
lines changed

7 files changed

+69
-179
lines changed

ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/LedgerDB/API.hs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,14 @@ data TestInternals m l blk = TestInternals
304304
{ wipeLedgerDB :: m ()
305305
, takeSnapshotNOW :: WhereToTakeSnapshot -> Maybe String -> m ()
306306
, push :: ExtLedgerState blk DiffMK -> m ()
307+
-- ^ Push a ledger state, and prune the 'LedgerDB' to its immutable tip.
308+
--
309+
-- This does not modify the set of previously applied points.
307310
, reapplyThenPushNOW :: blk -> m ()
311+
-- ^ Apply block to the tip ledger state (using reapplication), and prune the
312+
-- 'LedgerDB' to its immutable tip.
313+
--
314+
-- This does not modify the set of previously applied points.
308315
, truncateSnapshots :: m ()
309316
, closeLedgerDB :: m ()
310317
, getNumLedgerTablesHandles :: m Word64
@@ -462,11 +469,10 @@ data InitDB db m blk = InitDB
462469
-- ^ Closing the database, to be reopened again with a different snapshot or
463470
-- with the genesis state.
464471
, initReapplyBlock :: !(LedgerDbCfg (ExtLedgerState blk) -> blk -> db -> m db)
465-
-- ^ Reapply a block from the immutable DB when initializing the DB.
472+
-- ^ Reapply a block from the immutable DB when initializing the DB. Prune the
473+
-- LedgerDB such that there are no volatile states.
466474
, currentTip :: !(db -> LedgerState blk EmptyMK)
467475
-- ^ Getting the current tip for tracing the Ledger Events.
468-
, pruneDb :: !(db -> m db)
469-
-- ^ Prune the database so that no immutable states are considered volatile.
470476
, mkLedgerDb ::
471477
!(db -> m (LedgerDB m (ExtLedgerState blk) blk, TestInternals m (ExtLedgerState blk) blk))
472478
-- ^ Create a LedgerDB from the initialized data structures from previous
@@ -551,13 +557,7 @@ initialize
551557
Left err -> do
552558
closeDb initDb
553559
error $ "Invariant violation: invalid immutable chain " <> show err
554-
Right (db, replayed) -> do
555-
db' <- pruneDb dbIface db
556-
return
557-
( acc InitFromGenesis
558-
, db'
559-
, replayed
560-
)
560+
Right (db, replayed) -> return (acc InitFromGenesis, db, replayed)
561561
tryNewestFirst acc (s : ss) = do
562562
eInitDb <- initFromSnapshot s
563563
case eInitDb of
@@ -609,9 +609,7 @@ initialize
609609
Monad.when (diskSnapshotIsTemporary s) $ deleteSnapshot hasFS s
610610
closeDb initDb
611611
tryNewestFirst (acc . InitFailure s err) ss
612-
Right (db, replayed) -> do
613-
db' <- pruneDb dbIface db
614-
return (acc (InitFromSnapshot s pt), db', replayed)
612+
Right (db, replayed) -> return (acc (InitFromSnapshot s pt), db, replayed)
615613

616614
replayTracer' =
617615
decorateReplayTracerWithGoal
@@ -784,8 +782,6 @@ type LedgerSupportsLedgerDB blk =
784782
data LedgerDbPrune
785783
= -- | Prune all states, keeping only the current tip.
786784
LedgerDbPruneAll
787-
| -- | Prune to only keep the last @k@ states.
788-
LedgerDbPruneKeeping SecurityParam
789785
| -- | Prune such that all (non-anchor) states are not older than the given
790786
-- slot.
791787
LedgerDbPruneBeforeSlot SlotNo

ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/LedgerDB/V1.hs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ mkInitDb args bss getBlock =
121121
else pure chlog'
122122
pure (chlog'', r, bstore)
123123
, currentTip = \(ch, _, _) -> ledgerState . current $ ch
124-
, pruneDb = \(ch, r, bs) -> pure (pruneToImmTipOnly ch, r, bs)
125124
, mkLedgerDb = \(db, ldbBackingStoreKey, ldbBackingStore) -> do
126125
(varDB, prevApplied) <-
127126
(,) <$> newTVarIO db <*> newTVarIO Set.empty
@@ -437,7 +436,7 @@ implIntPush ::
437436
LedgerDBEnv m l blk -> l DiffMK -> m ()
438437
implIntPush env st = do
439438
chlog <- readTVarIO $ ldbChangelog env
440-
let chlog' = prune (LedgerDbPruneKeeping (ledgerDbCfgSecParam $ ldbCfg env)) $ extend st chlog
439+
let chlog' = pruneToImmTipOnly $ extend st chlog
441440
atomically $ writeTVar (ldbChangelog env) chlog'
442441

443442
implIntReapplyThenPush ::

ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/LedgerDB/V1/DbChangelog.hs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -359,37 +359,27 @@ reapplyThenPush ::
359359
DbChangelog l ->
360360
m (DbChangelog l)
361361
reapplyThenPush cfg ap ksReader db =
362-
(\current' -> prune (LedgerDbPruneKeeping (ledgerDbCfgSecParam cfg)) $ extend current' db)
362+
(\current' -> pruneToImmTipOnly $ extend current' db)
363363
<$> reapplyBlock (ledgerDbCfgComputeLedgerEvents cfg) (ledgerDbCfg cfg) ap ksReader db
364364

365-
-- | Prune oldest ledger states until at we have at most @k@ in the DbChangelog,
366-
-- excluding the one stored at the anchor.
365+
-- | Prune oldest ledger states according to the given 'LedgerDbPrune' strategy.
367366
--
368367
-- +--------------+----------------------------+----------------------+
369368
-- | lastFlushed | states | tableDiffs |
370369
-- +==============+============================+======================+
371370
-- | @L0@ | @L0 :> [ L1, L2, L3, L4 ]@ | @[ D1, D2, D3, D4 ]@ |
372371
-- +--------------+----------------------------+----------------------+
373-
-- | @>> prune (SecurityParam 3)@ |
372+
-- | @>> prune (LedgerDbPruneBeforeSlot 3)@ |
374373
-- +--------------+----------------------------+----------------------+
375374
-- | @L0@ | @L2 :> [ L3, L4 ]@ | @[ D1, D2, D3, D4 ]@ |
376375
-- +--------------+----------------------------+----------------------+
376+
--
377+
-- where the state @LX@ is from slot @X@.
377378
prune ::
378379
GetTip l =>
379380
LedgerDbPrune ->
380381
DbChangelog l ->
381382
DbChangelog l
382-
prune (LedgerDbPruneKeeping (SecurityParam k)) dblog =
383-
dblog{changelogStates = vol'}
384-
where
385-
DbChangelog{changelogStates} = dblog
386-
387-
nvol = AS.length changelogStates
388-
389-
vol' =
390-
if toEnum nvol <= unNonZero k
391-
then changelogStates
392-
else snd $ AS.splitAt (nvol - fromEnum (unNonZero k)) changelogStates
393383
prune LedgerDbPruneAll dblog =
394384
dblog{changelogStates = vol'}
395385
where

ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/LedgerDB/V2.hs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,6 @@ mkInitDb args flavArgs getBlock =
9191
x
9292
pure y
9393
, currentTip = ledgerState . current
94-
, pruneDb = \lseq -> do
95-
let (rel, dbPrunedToImmDBTip) = pruneToImmTipOnly lseq
96-
rel
97-
pure dbPrunedToImmDBTip
9894
, mkLedgerDb = \lseq -> do
9995
varDB <- newTVarIO lseq
10096
prevApplied <- newTVarIO Set.empty
@@ -211,8 +207,9 @@ mkInternals bss h =
211207
eFrk <- newForkerAtTarget h reg VolatileTip
212208
case eFrk of
213209
Left{} -> error "Unreachable, Volatile tip MUST be in LedgerDB"
214-
Right frk ->
210+
Right frk -> do
215211
forkerPush frk st >> atomically (forkerCommit frk) >> forkerClose frk
212+
getEnv h pruneLedgerSeq
216213
, reapplyThenPushNOW = \blk -> getEnv h $ \env -> withRegistry $ \reg -> do
217214
eFrk <- newForkerAtTarget h reg VolatileTip
218215
case eFrk of
@@ -227,6 +224,7 @@ mkInternals bss h =
227224
blk
228225
(st `withLedgerTables` tables)
229226
forkerPush frk st' >> atomically (forkerCommit frk) >> forkerClose frk
227+
pruneLedgerSeq env
230228
, wipeLedgerDB = getEnv h $ destroySnapshots . ldbHasFS
231229
, closeLedgerDB =
232230
let LDBHandle tvar = h
@@ -249,6 +247,10 @@ mkInternals bss h =
249247
InMemoryHandleArgs -> InMemory.takeSnapshot
250248
LSMHandleArgs x -> absurd x
251249

250+
pruneLedgerSeq :: LedgerDBEnv m (ExtLedgerState blk) blk -> m ()
251+
pruneLedgerSeq env =
252+
join $ atomically $ stateTVar (ldbSeq env) $ pruneToImmTipOnly
253+
252254
-- | Testing only! Truncate all snapshots in the DB.
253255
implIntTruncateSnapshots :: MonadThrow m => SomeHasFS m -> m ()
254256
implIntTruncateSnapshots sfs@(SomeHasFS fs) = do

ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/LedgerDB/V2/LedgerSeq.hs

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
{-# LANGUAGE StandaloneDeriving #-}
1515
{-# LANGUAGE TypeOperators #-}
1616
{-# LANGUAGE UndecidableInstances #-}
17-
{-# LANGUAGE ViewPatterns #-}
1817

1918
-- | The data structure that holds the cached ledger states.
2019
module Ouroboros.Consensus.Storage.LedgerDB.V2.LedgerSeq
@@ -206,7 +205,7 @@ reapplyThenPush ::
206205
LedgerSeq m l ->
207206
m (m (), LedgerSeq m l)
208207
reapplyThenPush rr cfg ap db =
209-
(\current' -> prune (LedgerDbPruneKeeping (ledgerDbCfgSecParam cfg)) $ extend current' db)
208+
(\current' -> pruneToImmTipOnly $ extend current' db)
210209
<$> reapplyBlock (ledgerDbCfgComputeLedgerEvents cfg) (ledgerDbCfg cfg) ap rr db
211210

212211
reapplyBlock ::
@@ -229,28 +228,23 @@ reapplyBlock evs cfg b _rr db = do
229228
pushDiffs newtbs st st'
230229
pure (StateRef newst newtbs)
231230

232-
-- | Prune older ledger states until at we have at most @k@ volatile states in
233-
-- the LedgerDB, plus the one stored at the anchor.
231+
-- | Prune older ledger states according to the given 'LedgerDbPrune' strategy.
234232
--
235233
-- The @fst@ component of the returned value is an action closing the pruned
236234
-- ledger states.
237235
--
238236
-- >>> ldb = LedgerSeq $ AS.fromOldestFirst l0 [l1, l2, l3]
239237
-- >>> ldb' = LedgerSeq $ AS.fromOldestFirst l1 [l2, l3]
240-
-- >>> snd (prune (LedgerDbPruneKeeping (SecurityParam (unsafeNonZero 2))) ldb) == ldb'
238+
-- >>> snd (prune (LedgerDbPruneBeforeSlot 2) ldb) == ldb'
241239
-- True
240+
--
241+
-- where @lX@ is a ledger state from slot @X@.
242242
prune ::
243243
(Monad m, GetTip l) =>
244244
LedgerDbPrune ->
245245
LedgerSeq m l ->
246246
(m (), LedgerSeq m l)
247247
prune howToPrune (LedgerSeq ldb) = case howToPrune of
248-
LedgerDbPruneKeeping (SecurityParam (fromEnum . unNonZero -> k))
249-
| nvol <= k -> (pure (), LedgerSeq ldb)
250-
| otherwise -> (closeButHead before, LedgerSeq after)
251-
where
252-
nvol = AS.length ldb
253-
(before, after) = AS.splitAt (nvol - k) ldb
254248
LedgerDbPruneAll ->
255249
(closeButHead before, LedgerSeq after)
256250
where
@@ -298,15 +292,7 @@ extend newState =
298292
Reset
299293
-------------------------------------------------------------------------------}
300294

301-
-- | When creating a new @LedgerDB@, we should load whichever snapshot we find
302-
-- and then replay the chain up to the immutable tip. When we get there, the
303-
-- @LedgerDB@ will have a @k@-long sequence of states, which all come from
304-
-- immutable blocks, so we just prune all of them and only keep the last one as
305-
-- an anchor, as it is the immutable tip. Then we can proceed with opening the
306-
-- VolatileDB.
307-
--
308-
-- If we didn't do this step, the @LedgerDB@ would accept rollbacks into the
309-
-- immutable part of the chain, which must never be possible.
295+
-- | Set the volatile tip as the immutable tip and prune all older states.
310296
--
311297
-- >>> ldb = LedgerSeq $ AS.fromOldestFirst l0 [l1, l2, l3]
312298
-- >>> LedgerSeq ldb' = snd $ pruneToImmTipOnly ldb

ouroboros-consensus/test/storage-test/Test/Ouroboros/Storage/ChainDB/Model.hs

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ module Test.Ouroboros.Storage.ChainDB.Model
3333
, getBlock
3434
, getBlockByPoint
3535
, getBlockComponentByPoint
36-
, getDbChangelog
3736
, getIsValid
3837
, getLoEFragment
3938
, getMaxSlotNo
@@ -84,11 +83,7 @@ module Test.Ouroboros.Storage.ChainDB.Model
8483
, wipeVolatileDB
8584
) where
8685

87-
import Cardano.Ledger.BaseTypes
88-
( knownNonZeroBounded
89-
, nonZeroOr
90-
, unNonZero
91-
)
86+
import Cardano.Ledger.BaseTypes (unNonZero)
9287
import Codec.Serialise (Serialise, serialise)
9388
import Control.Monad (unless)
9489
import Control.Monad.Except (runExcept)
@@ -129,11 +124,6 @@ import Ouroboros.Consensus.Storage.ChainDB.API
129124
)
130125
import Ouroboros.Consensus.Storage.ChainDB.Impl.ChainSel (olderThanK)
131126
import Ouroboros.Consensus.Storage.Common ()
132-
import Ouroboros.Consensus.Storage.LedgerDB.API
133-
( LedgerDbCfgF (..)
134-
, LedgerDbPrune (..)
135-
)
136-
import qualified Ouroboros.Consensus.Storage.LedgerDB.V1.DbChangelog as DbChangelog
137127
import Ouroboros.Consensus.Util (repeatedly)
138128
import qualified Ouroboros.Consensus.Util.AnchoredFragment as Fragment
139129
import Ouroboros.Consensus.Util.IOLike (MonadSTM)
@@ -375,35 +365,6 @@ isValid ::
375365
Maybe Bool
376366
isValid = flip getIsValid
377367

378-
getDbChangelog ::
379-
(LedgerSupportsProtocol blk, LedgerTablesAreTrivial (LedgerState blk)) =>
380-
TopLevelConfig blk ->
381-
Model blk ->
382-
DbChangelog.DbChangelog' blk
383-
getDbChangelog cfg m@Model{..} =
384-
DbChangelog.prune tip
385-
. DbChangelog.reapplyThenPushMany' ledgerDbCfg blks
386-
$ DbChangelog.empty initLedger
387-
where
388-
blks = Chain.toOldestFirst $ currentChain m
389-
390-
k = configSecurityParam cfg
391-
392-
ledgerDbCfg =
393-
LedgerDbCfg
394-
{ ledgerDbCfgSecParam = k
395-
, ledgerDbCfg = ExtLedgerCfg cfg
396-
, ledgerDbCfgComputeLedgerEvents = OmitLedgerEvents
397-
}
398-
399-
tip =
400-
case maxActualRollback k m of
401-
0 -> LedgerDbPruneAll
402-
n ->
403-
-- Since we know that @`n`@ is not zero, it is impossible for `nonZeroOr`
404-
-- to return a `Nothing` and the final result to have default value of @`1`@.
405-
LedgerDbPruneKeeping $ SecurityParam $ nonZeroOr n $ knownNonZeroBounded @1
406-
407368
getLoEFragment :: Model blk -> LoE (AnchoredFragment blk)
408369
getLoEFragment = loeFragment
409370

0 commit comments

Comments
 (0)