Skip to content

Commit 073938c

Browse files
committed
Ensure that compared fragments always intersect
1 parent 30bd697 commit 073938c

File tree

3 files changed

+23
-16
lines changed

3 files changed

+23
-16
lines changed

ouroboros-network-api/src/Ouroboros/Network/BlockFetch/ConsensusInterface.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ data ChainComparison header =
212212
-- This is used as part of selecting which chains to prioritise for
213213
-- downloading block bodies.
214214
--
215+
-- PRECONDITION: The two fragments must intersect.
216+
--
215217
compareCandidateChains :: HasCallStack
216218
=> AnchoredFragment header
217219
-> AnchoredFragment header

ouroboros-network/src/Ouroboros/Network/BlockFetch/Decision.hs

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import Data.Set qualified as Set
3333
import Data.Function (on)
3434
import Data.Hashable
3535
import Data.List as List (foldl', groupBy, sortBy, transpose)
36-
import Data.Maybe (mapMaybe)
36+
import Data.Maybe (fromMaybe, mapMaybe)
3737
import Data.Set (Set)
3838

3939
import Control.Exception (assert)
@@ -473,8 +473,11 @@ empty fetch range, but this is ok since we never request empty ranges.
473473
--
474474
-- A 'ChainSuffix' must be non-empty, as an empty suffix, i.e. the candidate
475475
-- chain is equal to the current chain, would not be a plausible candidate.
476-
newtype ChainSuffix header =
477-
ChainSuffix { getChainSuffix :: AnchoredFragment header }
476+
data ChainSuffix header = ChainSuffix {
477+
getChainSuffix :: !(AnchoredFragment header)
478+
, -- | TODO
479+
getChainSuffixAfterImmutableTip :: !(AnchoredFragment header)
480+
}
478481

479482
{-
480483
We define the /chain suffix/ as the suffix of the candidate chain up until (but
@@ -511,25 +514,27 @@ interested in this candidate at all.
511514
-- current chain.
512515
--
513516
chainForkSuffix
514-
:: (HasHeader header, HasHeader block,
515-
HeaderHash header ~ HeaderHash block)
516-
=> AnchoredFragment block -- ^ Current chain.
517-
-> AnchoredFragment header -- ^ Candidate chain
517+
:: HasHeader header
518+
=> AnchoredFragment header
519+
-> AnchoredFragment header
518520
-> Maybe (ChainSuffix header)
519521
chainForkSuffix current candidate =
520522
case AF.intersect current candidate of
521523
Nothing -> Nothing
522-
Just (_, _, _, candidateSuffix) ->
524+
Just (currentPrefix, _, _, candidateSuffix) ->
523525
-- If the suffix is empty, it means the candidate chain was equal to
524526
-- the current chain and didn't fork off. Such a candidate chain is
525527
-- not a plausible candidate, so it must have been filtered out.
526528
assert (not (AF.null candidateSuffix)) $
527-
Just (ChainSuffix candidateSuffix)
529+
Just (ChainSuffix candidateSuffix candidateSuffixAfterImmTip)
530+
where
531+
candidateSuffixAfterImmTip =
532+
fromMaybe (error "unreachable TODO") (AF.join currentPrefix candidateSuffix)
533+
528534

529535
selectForkSuffixes
530-
:: (HasHeader header, HasHeader block,
531-
HeaderHash header ~ HeaderHash block)
532-
=> AnchoredFragment block
536+
:: HasHeader header
537+
=> AnchoredFragment header
533538
-> [(FetchDecision (AnchoredFragment header), peerinfo)]
534539
-> [(FetchDecision (ChainSuffix header), peerinfo)]
535540
selectForkSuffixes current chains =
@@ -743,7 +748,7 @@ prioritisePeerChains FetchModeDeadline salt compareCandidateChains blockFetchSiz
743748
(equatingPair
744749
-- compare on probability band first, then preferred chain
745750
(==)
746-
(equateCandidateChains `on` getChainSuffix)
751+
(equateCandidateChains `on` getChainSuffixAfterImmutableTip)
747752
`on`
748753
(\(band, chain, _fragments) -> (band, chain)))))
749754
. sortBy (descendingOrder
@@ -752,7 +757,7 @@ prioritisePeerChains FetchModeDeadline salt compareCandidateChains blockFetchSiz
752757
(comparingPair
753758
-- compare on probability band first, then preferred chain
754759
compare
755-
(compareCandidateChains `on` getChainSuffix)
760+
(compareCandidateChains `on` getChainSuffixAfterImmutableTip)
756761
`on`
757762
(\(band, chain, _fragments) -> (band, chain))))))
758763
. map annotateProbabilityBand
@@ -776,7 +781,7 @@ prioritisePeerChains FetchModeDeadline salt compareCandidateChains blockFetchSiz
776781
| EQ <- compareCandidateChains chain1 chain2 = True
777782
| otherwise = False
778783

779-
chainHeadPoint (_,ChainSuffix c,_) = AF.headPoint c
784+
chainHeadPoint (_,ChainSuffix c _,_) = AF.headPoint c
780785

781786
prioritisePeerChains FetchModeBulkSync salt compareCandidateChains blockFetchSize =
782787
map (\(decision, peer) ->

ouroboros-network/src/Ouroboros/Network/BlockFetch/Decision/Genesis.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ selectTheCandidate
468468
-- maximumBy yields the last element in case of a tie while we
469469
-- prefer the first one
470470
chainSfx = fst $
471-
List.foldl1' (maxChainOn (getChainSuffix . fst)) inRace
471+
List.foldl1' (maxChainOn (getChainSuffixAfterImmutableTip . fst)) inRace
472472
pure $ Just (chainSfx, inRace)
473473

474474
-- | Given _the_ candidate fragment to sync from, and a list of peers (with

0 commit comments

Comments
 (0)