diff --git a/ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/ChainDB/API.hs b/ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/ChainDB/API.hs index 6cc5b59668..d905d6b240 100644 --- a/ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/ChainDB/API.hs +++ b/ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/ChainDB/API.hs @@ -888,4 +888,7 @@ data LoE a = LoEEnabled !a deriving (Eq, Show, Generic, NoThunks, Functor, Foldable, Traversable) +-- | Get the current LoE fragment (if the LoE is enabled), see 'LoE' for more +-- details. This fragment must be anchored in a (recent) point on the immutable +-- chain, just like candidate fragments. type GetLoEFragment m blk = m (LoE (AnchoredFragment (Header blk))) diff --git a/ouroboros-consensus/test/storage-test/Test/Ouroboros/Storage/ChainDB/Model.hs b/ouroboros-consensus/test/storage-test/Test/Ouroboros/Storage/ChainDB/Model.hs index 458ac62bb1..0e277dde9d 100644 --- a/ouroboros-consensus/test/storage-test/Test/Ouroboros/Storage/ChainDB/Model.hs +++ b/ouroboros-consensus/test/storage-test/Test/Ouroboros/Storage/ChainDB/Model.hs @@ -32,6 +32,7 @@ module Test.Ouroboros.Storage.ChainDB.Model ( , getBlockComponentByPoint , getIsValid , getLedgerDB + , getLoEFragment , getMaxSlotNo , hasBlock , hasBlockByPoint @@ -353,6 +354,9 @@ getLedgerDB cfg m@Model{..} = , ledgerDbCfg = ExtLedgerCfg cfg } +getLoEFragment :: Model blk -> LoE (AnchoredFragment blk) +getLoEFragment = loeFragment + {------------------------------------------------------------------------------- Construction -------------------------------------------------------------------------------} @@ -1012,6 +1016,10 @@ wipeVolatileDB cfg m = , cps = CPS.switchFork newChain (cps m) , currentLedger = newLedger , invalid = Map.empty + -- The LoE fragment must be anchored in an immutable point. Wiping the + -- VolDB can invalidate this when some immutable blocks have not yet + -- been persisted. + , loeFragment = Fragment.Empty Fragment.AnchorGenesis <$ loeFragment m } -- Get the chain ending at the ImmutableDB by doing chain selection on the diff --git a/ouroboros-consensus/test/storage-test/Test/Ouroboros/Storage/ChainDB/StateMachine.hs b/ouroboros-consensus/test/storage-test/Test/Ouroboros/Storage/ChainDB/StateMachine.hs index d7aad8fbef..b0bd2dc63c 100644 --- a/ouroboros-consensus/test/storage-test/Test/Ouroboros/Storage/ChainDB/StateMachine.hs +++ b/ouroboros-consensus/test/storage-test/Test/Ouroboros/Storage/ChainDB/StateMachine.hs @@ -432,7 +432,12 @@ run env@ChainDBEnv { varDB, .. } cmd = wipeVolatileDB :: ChainDBState m blk -> m (Point blk) wipeVolatileDB st = do close st - void $ atomically $ writeTMVar varVolatileDbFs Mock.empty + atomically $ do + writeTMVar varVolatileDbFs Mock.empty + -- The LoE fragment must be anchored in an immutable point. Wiping the + -- VolDB can invalidate this when some immutable blocks have not yet + -- been persisted. + writeTVar varLoEFragment $ AF.Empty AF.AnchorGenesis reopen env ChainDB { getTipPoint } <- chainDB <$> readTVarIO varDB atomically getTipPoint @@ -1070,6 +1075,7 @@ precondition :: forall m blk. TestConstraints blk precondition Model {..} (At cmd) = forAll (iters cmd) (`member` RE.keys knownIters) .&& forAll (flrs cmd) (`member` RE.keys knownFollowers) .&& + loeHasImmutableAnchor .&& case cmd of -- Even though we ensure this in the generator, shrinking might change -- it. @@ -1097,6 +1103,14 @@ precondition Model {..} (At cmd) = garbageCollectableIteratorNext it = Boolean $ Model.garbageCollectableIteratorNext secParam dbModel (knownIters RE.! it) + loeHasImmutableAnchor :: Logic + loeHasImmutableAnchor = case Model.getLoEFragment dbModel of + LoEEnabled frag -> + Boolean $ Chain.pointOnChain (AF.anchorPoint frag) immChain + LoEDisabled -> Top + where + immChain = Model.immutableChain secParam dbModel + cfg :: TopLevelConfig blk cfg = unOpaque modelConfig