Skip to content
This repository was archived by the owner on Aug 18, 2020. It is now read-only.

Commit fddd259

Browse files
iohk-bors[bot]erikdintricate
committed
Merge #3966
3966: CBR-497: Adapt epoch consolidation for OBFT r=erikd a=erikd ## Description The original epoch consolidation code only worked for Ouroborous classic epochs which had an epoch boundary block (EBB) between each epoch. OBFT has epochs just like classic, but does not have EBBs. This commit modifies the existing epoch consolidation code so that it works on both classic and OBFT epochs. ## Linked issue https://iohk.myjetbrains.com/youtrack/issue/CBR-497 ## QA Steps Sync the whole mainnet block chain (which is Ouroboros Classic/Original). Currently not able to test OBFT. Co-authored-by: Erik de Castro Lopo <[email protected]> Co-authored-by: Luke Nadur <[email protected]>
2 parents 5ce27bc + ee7828e commit fddd259

File tree

1 file changed

+46
-45
lines changed

1 file changed

+46
-45
lines changed

db/src/Pos/DB/Block/Epoch.hs

+46-45
Original file line numberDiff line numberDiff line change
@@ -219,34 +219,22 @@ getConsolidatedSerBlund (SlotId ei lsi) = do
219219
-- -----------------------------------------------------------------------------
220220

221221
data ConsolidateError
222-
= CEFinalBlockNotBoundary !Text
223-
| CEExpectedGenesis !Text !HeaderHash
224-
| CEExcpectedMain !Text !HeaderHash
222+
= CEExpectedMain !Text !HeaderHash
225223
| CEForwardLink !Text !HeaderHash
226224
| CEEoSLookupFailed !Text !HeaderHash
227225
| CEBlockLookupFailed !Text !LocalSlotIndex !HeaderHash
228-
| CEBOffsetFail !Text
229-
| CEBlockMismatch !Text !LocalSlotIndex
230226
| CEBBlockNotFound !Text !LocalSlotIndex !HeaderHash
231227

232228
renderConsolidateError :: ConsolidateError -> Text
233229
renderConsolidateError = \case
234-
CEFinalBlockNotBoundary fn ->
235-
fn <> ": Final block is not an epoch boundary block"
236-
CEExpectedGenesis fn h ->
237-
fn <> sformat (": hash " % build % " should be an epoch boundary hash.") h
238-
CEExcpectedMain fn h ->
230+
CEExpectedMain fn h ->
239231
fn <> sformat (": hash " % build % " should be a main block hash.") h
240232
CEForwardLink fn h ->
241233
fn <> sformat (": failed to follow hash " % build) h
242234
CEEoSLookupFailed fn h ->
243235
fn <> sformat (": EpochOrSlot lookup failed on hash " % build) h
244236
CEBlockLookupFailed fn lsi h ->
245237
fn <> sformat (": block lookup failed on (" % build % ", " % build % ")") lsi h
246-
CEBOffsetFail fn ->
247-
fn <> ": Failed to find offset"
248-
CEBlockMismatch fn lsi ->
249-
fn <> sformat (": block mismatch at index " % build) lsi
250238
CEBBlockNotFound fn lsi hh ->
251239
fn <> sformat (": block mssing : " % build % " " % build) lsi hh
252240

@@ -334,15 +322,15 @@ consolidateWithStatus
334322
=> ConsolidateCheckPoint -> ConsolidateStatus -> SlotCount -> m ConsolidateStatus
335323
consolidateWithStatus checkPoint oldStatus epochSlots = do
336324
enCpp <- runExceptT $ consolidateOneEpoch checkPoint epochSlots
337-
-- 'tipEpoch' is the tip of the block chain that has been synced by this node so far.
338-
tipEpoch <- getTipEpoch
339-
logInfo $ sformat ("consolidated epoch "%int%", current tip is epoch "%int)
340-
(getEpochIndex $ ccpEpochIndex checkPoint) (getEpochIndex tipEpoch)
341325
case enCpp of
342326
Left e -> do
343327
logError $ renderConsolidateError e
344328
pure $ increaseSyncSeconds oldStatus -- Not much else to be done!
345329
Right () -> do
330+
-- 'tipEpoch' is the tip of the block chain that has been synced by this node so far.
331+
tipEpoch <- getTipEpoch
332+
logInfo $ sformat ("consolidated epoch "%int%", current tip is epoch "%int)
333+
(getEpochIndex $ ccpEpochIndex checkPoint) (getEpochIndex tipEpoch)
346334
pure $ if ccpEpochIndex checkPoint + 2 > tipEpoch
347335
then increaseSyncSeconds oldStatus
348336
else resetSyncSeconds oldStatus
@@ -352,14 +340,14 @@ consolidateOneEpoch
352340
:: ConsolidateM ctx m
353341
=> ConsolidateCheckPoint -> SlotCount -> ExceptT ConsolidateError m ()
354342
consolidateOneEpoch ccp epochSlots = do
355-
(epochBoundary, sihs) <- getEpochHeaderHashes $ ccpHeaderHash ccp
343+
(epochStart, sihs) <- getEpochHeaderHashes $ ccpHeaderHash ccp
356344
(epochPath, indexPath) <- mkEpochPaths (ccpEpochIndex ccp) . view epochDataDir <$> getNodeDBs
357345

358346
xs <- consolidateEpochBlocks epochPath sihs
359347
liftIO $ writeEpochIndex epochSlots indexPath xs
360348

361349
-- Write starting point for next consolidation to the MiscDB.
362-
putConsolidateCheckPoint $ ConsolidateCheckPoint (ccpEpochIndex ccp + 1) epochBoundary
350+
putConsolidateCheckPoint $ ConsolidateCheckPoint (ccpEpochIndex ccp + 1) epochStart
363351

364352
-- After the check point is written, delete old blunds for the epoch we have just
365353
-- consolidated.
@@ -415,36 +403,48 @@ consolidateEpochBlocks fpath xs = ExceptT $ do
415403
pure . Right $ SlotIndexLength (getSlotIndex lsi)
416404
(fromIntegral $ LBS.length chunk)
417405

418-
-- | Given the hash of an epoch boundary block, return a pair of the next
419-
-- epoch boundary hash and a list of the header hashes of the main blocks
420-
-- between the two boundary blocks.
406+
-- | Get a list of headers for an epoch.
407+
-- This function is designed to work on both Ouroboros classic (Original)
408+
-- epochs and on Ouroboros BFT epochs. The only difference between these two
409+
-- epoch types from the point of view of block consolidation is that Original
410+
-- epochs start with an epoch boundary block (EBB) where as OBFT doesn't have
411+
-- EBBs.
412+
-- The inital header hash that is passed in should be the hash of either the
413+
-- EBB for Original or of the zeroth block in the case of OBFT.
421414
getEpochHeaderHashes
422415
:: MonadDBRead m
423416
=> HeaderHash -> ExceptT ConsolidateError m (HeaderHash, [SlotIndexHash])
424-
getEpochHeaderHashes ghash = do
425-
mbh <- isMainBlockHeader ghash
426-
when mbh $
427-
throwE $ CEExpectedGenesis "getEpochHeaderHashes" ghash
428-
(ng, bhs) <- loop [] ghash
429-
whenM (isMainBlockHeader ng) $
430-
throwE $ CEFinalBlockNotBoundary "getEpochHeaderHashes"
431-
pure (ng, reverse bhs)
417+
getEpochHeaderHashes startHash = do
418+
-- Make sure the hash passed to the OBFT version is a Main block and not an
419+
-- epoch boundary block.
420+
next <- ifM (isMainBlockHeader startHash)
421+
(pure startHash)
422+
(maybe (throwE $ errorHash startHash) pure =<< resolveForwardLink startHash)
423+
424+
-- For most epochs, the LocalSlotIndex here should be zero, but there is at
425+
-- least one exception to the rule, epoch 84 which suffered a chain stall
426+
-- and missed the first 772 slots.
427+
lsi <- getLocalSlotIndex next
428+
ei <- getBlockHeaderEpoch next
429+
(nh, bhs) <- loop ei [SlotIndexHash lsi next] next
430+
pure (nh, reverse bhs)
432431
where
433432
loop
434433
:: MonadDBRead m
435-
=> [SlotIndexHash] -> HeaderHash
434+
=> EpochIndex -> [SlotIndexHash] -> HeaderHash
436435
-> ExceptT ConsolidateError m (HeaderHash, [SlotIndexHash])
437-
loop !acc hash = do
436+
loop currentEpoch !acc hash = do
438437
mnext <- resolveForwardLink hash
439438
next <- maybe (throwE $ errorHash hash) pure mnext
440-
ifM (not <$> isMainBlockHeader next)
441-
(pure (next, acc))
442-
(do lsi <- getLocalSlotIndex next
443-
loop (SlotIndexHash lsi next : acc) next
444-
)
439+
nei <- getBlockHeaderEpoch next
440+
if nei /= currentEpoch
441+
then pure (next, acc)
442+
else do
443+
lsi <- getLocalSlotIndex next
444+
loop currentEpoch (SlotIndexHash lsi next : acc) next
445445

446-
errorHash hash =
447-
CEForwardLink "getEpochHeaderHashes" hash
446+
errorHash =
447+
CEForwardLink "getEpochHeaderHashes"
448448

449449
getLocalSlotIndex
450450
:: MonadDBRead m
@@ -453,7 +453,7 @@ getLocalSlotIndex hh = do
453453
meos <- unEpochOrSlot <<$>> getHeaderEpochOrSlot hh
454454
case meos of
455455
Nothing -> throwE $ CEEoSLookupFailed "getLocalSlotIndex" hh
456-
Just (Left _) -> throwE $ CEExcpectedMain "getLocalSlotIndex" hh
456+
Just (Left _) -> throwE $ CEExpectedMain "getLocalSlotIndex" hh
457457
Just (Right sid) -> pure $ siSlot sid
458458

459459
isMainBlockHeader :: MonadDBRead m => HeaderHash -> m Bool
@@ -523,8 +523,10 @@ data ConsolidateCheckPoint = ConsolidateCheckPoint
523523
{ ccpEpochIndex :: !EpochIndex
524524
-- ^ The EpochIndex of the next epoch to be consolidated.
525525
, ccpHeaderHash :: !HeaderHash
526-
-- ^ The HeaderHash of the boundary block separating the last consolidated
527-
-- epoch and the next one to be consolidated.
526+
-- ^ The HeaderHash of first block of the next epoch. In the case of
527+
-- Ouroboros Original/Classic, this will be the epoch boundary block
528+
-- and in the case of OBFT, this with be the zeroth block of the next
529+
-- epoch.
528530
}
529531

530532
-- | Get the 'HeaderHash' of the marking the start of the first un-consolidated
@@ -538,8 +540,7 @@ getConsolidateCheckPoint genesisHash =
538540
Just eh -> pure eh
539541
Nothing -> ConsolidateCheckPoint 0 <$> getFirstGenesisBlockHash genesisHash
540542

541-
-- | Store the hash of the epoch boundary block which is at the start of the
542-
-- next epoch to be consolidated.
543+
-- | Store the consolidation check point.
543544
putConsolidateCheckPoint :: MonadDB m => ConsolidateCheckPoint -> m ()
544545
putConsolidateCheckPoint =
545546
miscPutBi consolidateCheckPointKey

0 commit comments

Comments
 (0)