Skip to content

Commit 2300282

Browse files
committed
ouroboros-consensus: add ChainDB.waitForImmutableBlock
This function allows waiting until the immutables DB's tip is past the target slot.
1 parent 9119746 commit 2300282

File tree

4 files changed

+42
-0
lines changed

4 files changed

+42
-0
lines changed

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,16 @@ data ChainDB m blk = ChainDB
405405
, getPerasCertSnapshot :: STM m (PerasCertSnapshot blk)
406406
-- ^ Get the Peras certificate snapshot, containing the currently-known
407407
-- certificates boosting blocks newer than the immutable tip.
408+
, waitForImmutableBlock :: RealPoint blk -> m (Maybe (RealPoint blk))
409+
-- ^ wait until the immutable tip gets past the given slot:
410+
-- - returns the block when it becomes the immutable tip,
411+
-- reading it from disk;
412+
-- - if no block was found at the target slot, returns the immutable block
413+
-- at the next filled slot;
414+
-- - returns 'Nothing' if no block was found on disk at all.
415+
--
416+
-- Currently, the only use-case of this function is to verify the immutability
417+
-- of a block from the big ledger peer snapshot file.
408418
, closeDB :: m ()
409419
-- ^ Close the ChainDB
410420
--

ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/ChainDB/Impl.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ openDBInternal args launchBgTasks = runWithTempRegistry $ do
290290
, addPerasCertAsync = getEnv1 h ChainSel.addPerasCertAsync
291291
, getPerasWeightSnapshot = getEnvSTM h Query.getPerasWeightSnapshot
292292
, getPerasCertSnapshot = getEnvSTM h Query.getPerasCertSnapshot
293+
, waitForImmutableBlock = getEnv1 h Query.waitForImmutableBlock
293294
}
294295
addBlockTestFuse <- newFuse "test chain selection"
295296
copyTestFuse <- newFuse "test copy to immutable db"

ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/ChainDB/Impl/Query.hs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
{-# LANGUAGE FlexibleContexts #-}
22
{-# LANGUAGE GADTs #-}
3+
{-# LANGUAGE LambdaCase #-}
34
{-# LANGUAGE MultiWayIf #-}
5+
{-# LANGUAGE NamedFieldPuns #-}
46
{-# LANGUAGE RecordWildCards #-}
57
{-# LANGUAGE ScopedTypeVariables #-}
8+
{-# LANGUAGE TypeApplications #-}
69
{-# LANGUAGE TypeOperators #-}
710

811
-- | Queries
@@ -26,6 +29,7 @@ module Ouroboros.Consensus.Storage.ChainDB.Impl.Query
2629
, getTipBlock
2730
, getTipHeader
2831
, getTipPoint
32+
, waitForImmutableBlock
2933

3034
-- * Low-level queries
3135
, getAnyBlockComponent
@@ -34,6 +38,7 @@ module Ouroboros.Consensus.Storage.ChainDB.Impl.Query
3438
, getChainSelStarvation
3539
) where
3640

41+
import Cardano.Ledger.BaseTypes (WithOrigin (..))
3742
import Control.ResourceRegistry (ResourceRegistry)
3843
import qualified Data.Map.Strict as Map
3944
import qualified Data.Set as Set
@@ -296,6 +301,24 @@ getPerasCertSnapshot ::
296301
ChainDbEnv m blk -> STM m (PerasCertSnapshot blk)
297302
getPerasCertSnapshot CDB{..} = PerasCertDB.getCertSnapshot cdbPerasCertDB
298303

304+
-- | Wait until the given point becomes immutable:
305+
-- - blocks until the immutable tip slot number is lower than the block's slot number;
306+
-- - ones the immutable tip is older than the slot of the target point:
307+
-- * returns the block at the target slot if it is occupied;n
308+
-- * otherwise, returns the block from the next occupied slot.
309+
waitForImmutableBlock ::
310+
forall blk m. IOLike m => ChainDbEnv m blk -> RealPoint blk -> m (Maybe (RealPoint blk))
311+
waitForImmutableBlock CDB{cdbImmutableDB} targetRealPoint = do
312+
-- first, wait until the target slot is older than the immutable tip
313+
_ <- atomically $ do
314+
ImmutableDB.getTip cdbImmutableDB >>= \case
315+
Origin -> retry
316+
At tip -> do
317+
check (ImmutableDB.tipSlotNo tip >= realPointSlot targetRealPoint)
318+
pure (ImmutableDB.tipToRealPoint tip)
319+
-- then, query the DB for a point at or directly following the target slot
320+
ImmutableDB.getBlockAtOrAfterPoint cdbImmutableDB targetRealPoint
321+
299322
{-------------------------------------------------------------------------------
300323
Unifying interface over the immutable DB and volatile DB, but independent
301324
of the ledger DB. These functions therefore do not require the entire

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,14 @@ data Cmd blk it flr
266266
-- something we are testing in 'prop_trace', see
267267
-- 'invalidBlockNeverValidatedAgain'.
268268

269+
-- = No tests for waitForImmutableBlock
270+
--
271+
-- We do not test 'ChainDB.waitForImmutableBlock', because this test is
272+
-- sequential, and 'waitForImmutableBlock', which uses STM 'retry' and
273+
-- 'check' would block indefinitely.
274+
-- The core behaviour of 'waitForImmutableBlock' is tested in the ImmutableDB
275+
-- q-s-m test via testing 'ImmutableDB.getBlockAtOrAfterPoint'.
276+
269277
deriving instance SOP.Generic (Cmd blk it flr)
270278
deriving instance SOP.HasDatatypeInfo (Cmd blk it flr)
271279

0 commit comments

Comments
 (0)