Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
db39d20
Split the `BlockFetch.Decision` module
Niols Jun 5, 2024
c356465
Start writing a simple BlockFetch decision logic
Niols Jun 5, 2024
9771ed0
Note on “bulk sync”
Niols Jun 6, 2024
9b3693a
Get longest candidate
Niols Jun 10, 2024
5e4a665
Break down `filterNotAlreadyFetched` in two functions
Niols Jun 10, 2024
cc12e86
Break down `filterNotAlreadyInFlightWithPeer` in two functions
Niols Jun 10, 2024
47bd5c3
More work on bulk sync block fetch
Niols Jun 10, 2024
1cd371e
Filter plausible and in flight with other peer
Niols Jun 10, 2024
18e2fed
Yay movin' forward
Niols Jun 10, 2024
837d017
Choose the candidate to get and try to fetch it
Niols Jun 10, 2024
3d71e47
Getting there
Niols Jun 10, 2024
86fccf6
Move `fetchRequestDecision` to `Common`
Niols Jun 10, 2024
69b7c28
First implementation of a naive bulk sync decision logic
Niols Jun 10, 2024
d5b5fd2
Some notes here and there
Niols Jun 12, 2024
bc07066
Better filtering of peers if they don't provide the fragments
Niols Jun 12, 2024
5fffd66
A note
Niols Jun 12, 2024
c5c802b
Allow reading a peer queue in the consensus interface
Niols Jun 12, 2024
a535930
Use peer order in decision
Niols Jun 13, 2024
e37410c
Keep peers order internal
Niols Jun 13, 2024
3ac66dd
Add action to demote the dynamo
Niols Jun 13, 2024
9ffe465
Keep more granular decisions for each peer
Niols Jun 13, 2024
db3f862
Documentation
Niols Jun 14, 2024
54e6cbc
Some minor improvements
Niols Jun 14, 2024
32bfd08
Rewrite with new logic
Niols Jun 14, 2024
082fe81
Simplify types
Niols Jun 14, 2024
60ab44b
Make `selectTheCandidate` return a `WithDeclined`
Niols Jun 17, 2024
24ef98c
Make `selectThePeer` return a `WithDeclined`
Niols Jun 17, 2024
d56d2c5
Use actual `transformers`
Niols Jun 17, 2024
7ac4bb5
Remove `MaybeT` from `WithDeclined`
Niols Jun 17, 2024
4771b82
Inline `partitionEithersFirst`
Niols Jun 17, 2024
2953e5a
Some documentation
Niols Jun 17, 2024
238eb08
Document `selectThePeer`
Niols Jun 17, 2024
7c63658
Add the last ChainSel starvation time to consensus interface
Niols Jun 20, 2024
43951c4
Make `peerFetchBlocksInFlight` a map
Niols Jun 25, 2024
3a284db
Record the time at which a block was requested
Niols Jun 25, 2024
a44198a
Wrapper type for `PeersOrder`
Niols Jun 25, 2024
d4e295d
Revert "Record the time at which a block was requested"
Niols Jun 25, 2024
01faa03
The bulk sync decision function returns the actual request
Niols Jun 25, 2024
55465ac
Make `fetchDecisions` return a monadic action
Niols Jun 25, 2024
33afee7
Update the peers order following the blockfetch decision
Niols Jun 25, 2024
6587d1c
Write the peers order and record the start time
Niols Jun 26, 2024
1154905
Check last ChainSel starvation
Niols Jun 26, 2024
3c4aae7
Make grace period very small for testing purposes
Niols Jun 26, 2024
dfe0abd
Get more information from ChainSel starvation
Niols Jun 27, 2024
f32d171
Export `mcons` and `msnoc` close to `PeersOrder`
Niols Jun 27, 2024
fda748d
More efficient implementation of `trimFragmentsToCandidate`
Niols Jun 28, 2024
cc689fb
Some fixes
Niols Jul 3, 2024
d63b00a
Some comments and types
Niols Jul 3, 2024
354fec9
[TRYOUT] Get rid of some `tell`s
Niols Jul 5, 2024
1b8072f
Grace period of 10 seconds
Niols Jul 5, 2024
c8b8cc5
Make grace period configurable
Niols Jul 5, 2024
b3650ee
Fix handling of ongoing starvation
Niols Jul 5, 2024
0308e0c
Make `fetchTheCandidate` also return a Writer Maybe
Niols Jul 8, 2024
1b717f2
Switch to CPS Writer
Niols Jul 8, 2024
2ba5078
Revert "[TRYOUT] Get rid of some `tell`s"
Niols Jul 8, 2024
1b8a232
Avoid `Writer [a]`
Niols Jul 8, 2024
e58a48f
More performant (hopefully) `toList`
Niols Jul 9, 2024
dd92744
Mark blocks as ignored when demoting peer
Niols Jul 8, 2024
37622e2
Ignore blocks when choosing the peer to sync from
Niols Jul 9, 2024
85d9cc7
Fix duplication in peers order
Niols Jul 9, 2024
8ab4062
Also ignore blocks in flight by other peers in actual request, and co…
Niols Jul 9, 2024
e475726
Code cleanup
Niols Jul 9, 2024
3b978c1
Cleanup
Niols Jul 10, 2024
89ffb2e
Remove useless comment
Niols Jul 11, 2024
d4a453d
Improve comments of `filterNotAlready...`
Niols Jul 11, 2024
0be0889
Mention that grossRequest implies refinedRequest
Niols Jul 11, 2024
d28e315
Apply suggestions by @facundominguez
Niols Jul 11, 2024
3890175
Check if blocks in flight before demoting
Niols Jul 11, 2024
9e69d60
Compatiblity with older GHC/packages in `cardano-node`
nbacquey Jul 11, 2024
8c07b58
Fix `PeersOrder`
Niols Jul 11, 2024
59c11f9
Move important part of `fetchDecisions` into BulkSync
Niols Jul 11, 2024
4361031
Bring back everything to `Deadline`
Niols Jul 11, 2024
7044561
Rename `checkChangeOfCurrentPeer` to `maybeSetCurrentPeer`
Niols Jul 12, 2024
7dd8434
Better comment for `filterNotAlreadyInFlightWithPeer`
Niols Jul 12, 2024
f43032b
First draft documentation for BulkSync
Niols Jul 12, 2024
bc4451e
Re-record a new start time when no inflight blocks
Niols Jul 12, 2024
40ec6bc
Switch gross request to 20 mebibytes
Niols Jul 12, 2024
4438847
Document on `grossRequest`'s non-emptiness
Niols Jul 12, 2024
d615b8f
Remove useless `FIXME`
Niols Jul 12, 2024
2ca7b8b
`fetchDecisions` (mind the s) is only used by `FetchModeDeadline`
Niols Jul 12, 2024
9f338a4
Remove unused argument `maxConcurrencyBulkSync`
Niols Jul 12, 2024
4205e68
Document the interaction with CSJ
Niols Jul 12, 2024
04be7c4
Add documentation about the gross request
Niols Jul 12, 2024
e5db153
Mebibytes, not megabytes ---
Niols Jul 12, 2024
4ec0778
Ignore all blocks in flight when demoting
Niols Jul 12, 2024
d35ab47
Keep using the same peer until it starves us
Niols Jul 12, 2024
90084d4
Avoid having two slightly-different notions of current peers
Niols Jul 12, 2024
4c84463
Last fixes
Niols Jul 12, 2024
2d2d07a
A proper datatype for blockfetch decision tracing
Niols Jul 15, 2024
8db3f2d
Remove useless `filterNotAlreadyInFlightWithAny...`
Niols Jul 15, 2024
270c02e
`filterNot` -> `drop`
Niols Jul 15, 2024
4ba0e83
typos
Niols Jul 15, 2024
33ffeb3
Trace when peer starved us
Niols Jul 15, 2024
7a84d64
Extract Genesis-specific config params in their own type
nbacquey Jul 16, 2024
bef3798
Update documentation to the latest design
Niols Jul 17, 2024
a508f06
Make in-flight blocks a set again
Niols Jul 17, 2024
c451191
Current peer only if inflight blocks
Niols Jul 19, 2024
3626625
Put only one block in the gross request
facundominguez Jul 19, 2024
ba6d7ea
Add missing instances for GenesisBlockFetchCOnfiguration
nbacquey Jul 22, 2024
33bcad5
Drop the empty fragments from the final request
facundominguez Jul 22, 2024
6e6eae8
Remove extractFirstElement
facundominguez Jul 22, 2024
6a2e8d8
Remove eqPeerInfo
facundominguez Jul 22, 2024
59c250b
Rename fetchTheCandidate to makeFetchRequest
facundominguez Jul 22, 2024
1626277
Groom comments
facundominguez Jul 22, 2024
2a4d66b
Groom auxiliary definition theFragments
facundominguez Jul 22, 2024
546adc4
Groom fetchDecisionsBulkSync
facundominguez Jul 22, 2024
d7c1196
Address review comment to optimize checks when selecting the peer
facundominguez Jul 22, 2024
b24e05c
Groom comments
facundominguez Jul 22, 2024
fe917f3
Use peerInfoPeer instead of pattern matching
facundominguez Jul 22, 2024
717d49f
Retrieve PeerInfo of the current peer where it is used
facundominguez Jul 22, 2024
ff1d5ac
Groom makeFetchRequest
facundominguez Jul 22, 2024
460d18f
Revert "Note on “bulk sync”"
facundominguez Jul 24, 2024
7686f9c
Set the default decision loop interval to 40 ms
facundominguez Jul 24, 2024
7284bda
Separate the decision loop interval for bulksync and deadline modes
facundominguez Jul 25, 2024
34c829f
Make the output more descriptive on failures of the BlockFetch tests
facundominguez Jul 24, 2024
439116a
Fix typo in error message
facundominguez Jul 24, 2024
f4a335d
Have failing BlockFetch tests terminate
facundominguez Jul 25, 2024
ad95337
Fix expectations of test 'static chains without overlap'
facundominguez Jul 25, 2024
178872f
Fix expectations of test 'static chains with overlap'
facundominguez Jul 26, 2024
38152f3
Refactoring: resolve declination of the candidate fragments early
facundominguez Jul 26, 2024
43b4491
Sort the peers only once in the decision logic
facundominguez Jul 26, 2024
f6a9152
Don't update de peers order prematurely
facundominguez Jul 26, 2024
60ea108
Change the current peer if it cannot provide the gross request
facundominguez Jul 26, 2024
27c819d
Put the current peer at the front of the peers order
facundominguez Jul 26, 2024
4373d13
Relax the predicates of 'static chains with/out overlap'
facundominguez Jul 26, 2024
0675bfc
Rename BlockFetch tests that only test BulkSync mode
facundominguez Jul 26, 2024
427c92d
fixup: Separate the decision loop interval for bulksync and deadline …
facundominguez Jul 26, 2024
576a425
Delete extract
facundominguez Jul 27, 2024
441d6d7
Update the current peer every time it has changed.
facundominguez Jul 29, 2024
69986a2
Adjust documentation after putting the current peer at the front of p…
facundominguez Jul 29, 2024
9ad28ad
Flip calls to align peers and check starvation
facundominguez Jul 30, 2024
6438401
Run the BlockFetch logic at least once every grace period
facundominguez Jul 30, 2024
6162644
Use compareCandidateChains to select a chain in BulkSync BlockFetch
facundominguez Jul 30, 2024
45ec560
Replace custom type ListConcat with DList
nbacquey Aug 1, 2024
12a0f1f
use `Seq` instead of `List` for `peersOrderAll`
nbacquey Aug 1, 2024
9abfde5
Replace filter by assertion when building gross request
nbacquey Aug 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}

module Ouroboros.Network.BlockFetch.ConsensusInterface
( FetchMode (..)
, BlockFetchConsensusInterface (..)
, WhetherReceivingTentativeBlocks (..)
, FromConsensus (..)
, ChainSelStarvation (..)
) where

import Control.Monad.Class.MonadSTM
import Control.Monad.Class.MonadTime (UTCTime)
import Control.Monad.Class.MonadTime.SI (Time)

import Data.Map.Strict (Map)
import GHC.Stack (HasCallStack)
import GHC.Generics (Generic)
import NoThunks.Class (NoThunks)

import Ouroboros.Network.AnchoredFragment (AnchoredFragment)
import Ouroboros.Network.Block
Expand Down Expand Up @@ -149,7 +155,17 @@ data BlockFetchConsensusInterface peer header block m =
-- PRECONDITION: Same as 'headerForgeUTCTime'.
--
-- WARNING: Same as 'headerForgeUTCTime'.
blockForgeUTCTime :: FromConsensus block -> STM m UTCTime
blockForgeUTCTime :: FromConsensus block -> STM m UTCTime,

-- | Information on the ChainSel starvation status; whether it is ongoing
-- or has ended recently. Needed by the bulk sync decision logic.
readChainSelStarvation :: STM m ChainSelStarvation,

-- | Action to inform CSJ that the given peer has not been performing
-- adequately with respect to BlockFetch, and that it should be demoted
-- from the dynamo role. Can be set to @const (pure ())@ in all other
-- scenarios.
demoteCSJDynamo :: peer -> m ()
}


Expand All @@ -159,6 +175,16 @@ data WhetherReceivingTentativeBlocks
= ReceivingTentativeBlocks
| NotReceivingTentativeBlocks

-- | Whether ChainSel is starved or has been recently.
--
-- The bulk sync fetch decision logic needs to decide whether the current
-- focused peer has starved ChainSel recently. This datatype is used to
-- represent this piece of information.
data ChainSelStarvation
= ChainSelStarvationOngoing
| ChainSelStarvationEndedAt Time
deriving (Eq, Show, NoThunks, Generic)

{-------------------------------------------------------------------------------
Syntactic indicator of key precondition about Consensus time conversions
-------------------------------------------------------------------------------}
Expand Down
16 changes: 12 additions & 4 deletions ouroboros-network/demo/chain-sync.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import Control.Concurrent.Async
import Control.Concurrent.Class.MonadSTM.Strict
import Control.Exception
import Control.Monad (when)
import Control.Monad.Class.MonadTime.SI (Time (..))
import Control.Tracer

import System.Directory
Expand Down Expand Up @@ -75,6 +76,7 @@ import Ouroboros.Network.Protocol.BlockFetch.Type qualified as BlockFetch
import Ouroboros.Network.BlockFetch
import Ouroboros.Network.BlockFetch.Client
import Ouroboros.Network.BlockFetch.ClientRegistry (FetchClientRegistry (..))
import Ouroboros.Network.BlockFetch.ConsensusInterface (ChainSelStarvation(..))
import Ouroboros.Network.DeltaQ (defaultGSV)


Expand Down Expand Up @@ -440,7 +442,10 @@ clientBlockFetch sockAddrs maxSlotNo = withIOManager $ \iocp -> do
blockMatchesHeader = \_ _ -> True,

headerForgeUTCTime,
blockForgeUTCTime = headerForgeUTCTime . fmap blockHeader
blockForgeUTCTime = headerForgeUTCTime . fmap blockHeader,

readChainSelStarvation = pure (ChainSelStarvationEndedAt (Time 0)),
demoteCSJDynamo = \_ -> pure ()
}
where
plausibleCandidateChain cur candidate =
Expand Down Expand Up @@ -506,11 +511,14 @@ clientBlockFetch sockAddrs maxSlotNo = withIOManager $ \iocp -> do
blockFetchPolicy
registry
(BlockFetchConfiguration {
bfcMaxConcurrencyBulkSync = 1,
bfcMaxConcurrencyDeadline = 2,
bfcMaxRequestsInflight = 10,
bfcDecisionLoopInterval = 0.01,
bfcSalt = 0
bfcDecisionLoopIntervalBulkSync = 0.04,
bfcDecisionLoopIntervalDeadline = 0.01,
bfcSalt = 0,
bfcGenesisBFConfig = GenesisBlockFetchConfiguration
{ gbfcBulkSyncGracePeriod = 10 -- seconds
}
})
>> return ()

Expand Down
6 changes: 6 additions & 0 deletions ouroboros-network/ouroboros-network.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ library
Ouroboros.Network.BlockFetch.ClientRegistry
Ouroboros.Network.BlockFetch.ClientState
Ouroboros.Network.BlockFetch.Decision
Ouroboros.Network.BlockFetch.Decision.BulkSync
Ouroboros.Network.BlockFetch.Decision.Deadline
Ouroboros.Network.BlockFetch.Decision.Trace
Ouroboros.Network.BlockFetch.DeltaQ
Ouroboros.Network.BlockFetch.State
Ouroboros.Network.DeltaQ
Expand Down Expand Up @@ -113,6 +116,7 @@ library
cborg >=0.2.1 && <0.3,
containers,
deepseq,
dlist,
dns,
hashable,
iproute,
Expand All @@ -121,6 +125,7 @@ library
nothunks,
psqueues >=0.2.3 && <0.3,
random,
transformers,

cardano-prelude,
cardano-slotting,
Expand Down Expand Up @@ -337,6 +342,7 @@ executable demo-chain-sync

contra-tracer,

si-timers,
typed-protocols,
strict-stm,
ouroboros-network-api,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@ import Ouroboros.Network.Block
import Network.TypedProtocol.Core
import Network.TypedProtocol.Pipelined

import qualified Ouroboros.Network.AnchoredFragment as AF
import Ouroboros.Network.ControlMessage (ControlMessageSTM)

import Ouroboros.Network.BlockFetch
import Ouroboros.Network.BlockFetch.Client
import Ouroboros.Network.BlockFetch.ConsensusInterface (ChainSelStarvation(..))
import Ouroboros.Network.Channel
import Ouroboros.Network.DeltaQ
import Ouroboros.Network.Driver
Expand All @@ -55,6 +57,7 @@ import Ouroboros.Network.Protocol.BlockFetch.Type
import Ouroboros.Network.Util.ShowProxy

import Ouroboros.Network.Mock.ConcreteBlock
import Ouroboros.Network.BlockFetch.Decision.Trace (TraceDecisionEvent)


-- | Run a single block fetch protocol until the chain is downloaded.
Expand All @@ -63,8 +66,7 @@ blockFetchExample0 :: forall m.
(MonadSTM m, MonadST m, MonadAsync m, MonadDelay m,
MonadFork m, MonadTime m, MonadTimer m, MonadMask m,
MonadThrow (STM m))
=> Tracer m [TraceLabelPeer Int
(FetchDecision [Point BlockHeader])]
=> Tracer m (TraceDecisionEvent Int BlockHeader)
-> Tracer m (TraceLabelPeer Int
(TraceFetchClientState BlockHeader))
-> Tracer m (TraceLabelPeer Int
Expand Down Expand Up @@ -134,11 +136,14 @@ blockFetchExample0 decisionTracer clientStateTracer clientMsgTracer
(sampleBlockFetchPolicy1 headerForgeUTCTime blockHeap currentChainHeaders candidateChainHeaders)
registry
(BlockFetchConfiguration {
bfcMaxConcurrencyBulkSync = 1,
bfcMaxConcurrencyDeadline = 2,
bfcMaxRequestsInflight = 10,
bfcDecisionLoopInterval = 0.01,
bfcSalt = 0
bfcDecisionLoopIntervalBulkSync = 0.04,
bfcDecisionLoopIntervalDeadline = 0.01,
bfcSalt = 0,
bfcGenesisBFConfig = GenesisBlockFetchConfiguration
{ gbfcBulkSyncGracePeriod = 10 -- seconds
}
})
>> return ()

Expand Down Expand Up @@ -172,8 +177,7 @@ blockFetchExample1 :: forall m.
(MonadSTM m, MonadST m, MonadAsync m, MonadDelay m,
MonadFork m, MonadTime m, MonadTimer m, MonadMask m,
MonadThrow (STM m))
=> Tracer m [TraceLabelPeer Int
(FetchDecision [Point BlockHeader])]
=> Tracer m (TraceDecisionEvent Int BlockHeader)
-> Tracer m (TraceLabelPeer Int
(TraceFetchClientState BlockHeader))
-> Tracer m (TraceLabelPeer Int
Expand Down Expand Up @@ -211,7 +215,7 @@ blockFetchExample1 decisionTracer clientStateTracer clientMsgTracer
driverAsync <- async $ do
threadId <- myThreadId
labelThread threadId "block-fetch-driver"
driver blockHeap
downloadTimer

-- Order of shutdown here is important for this example: must kill off the
-- fetch thread before the peer threads.
Expand Down Expand Up @@ -243,25 +247,25 @@ blockFetchExample1 decisionTracer clientStateTracer clientMsgTracer
(sampleBlockFetchPolicy1 headerForgeUTCTime blockHeap currentChainHeaders candidateChainHeaders)
registry
(BlockFetchConfiguration {
bfcMaxConcurrencyBulkSync = 1,
bfcMaxConcurrencyDeadline = 2,
bfcMaxRequestsInflight = 10,
bfcDecisionLoopInterval = 0.01,
bfcSalt = 0
bfcDecisionLoopIntervalBulkSync = 0.04,
bfcDecisionLoopIntervalDeadline = 0.01,
bfcSalt = 0,
bfcGenesisBFConfig = GenesisBlockFetchConfiguration
{ gbfcBulkSyncGracePeriod = 10 -- seconds
}
})
>> return ()

headerForgeUTCTime (FromConsensus x) =
pure $ convertSlotToTimeForTestsAssumingNoHardFork (blockSlot x)

driver :: TestFetchedBlockHeap m Block -> m ()
driver blockHeap = do
atomically $ do
heap <- getTestFetchedBlocks blockHeap
check $
all (\c -> AnchoredFragment.headPoint c `Set.member` heap)
candidateChains

-- | Terminates after 1 second per block in the candidate chains.
downloadTimer :: m ()
downloadTimer =
let totalBlocks = sum $ map AF.length candidateChains
in threadDelay (fromIntegral totalBlocks)

--
-- Sample block fetch configurations
Expand Down Expand Up @@ -293,7 +297,10 @@ sampleBlockFetchPolicy1 headerFieldsForgeUTCTime blockHeap currentChain candidat
blockMatchesHeader = \_ _ -> True,

headerForgeUTCTime = headerFieldsForgeUTCTime,
blockForgeUTCTime = headerFieldsForgeUTCTime
blockForgeUTCTime = headerFieldsForgeUTCTime,

readChainSelStarvation = pure (ChainSelStarvationEndedAt (Time 0)),
demoteCSJDynamo = \_ -> pure ()
}
where
plausibleCandidateChain cur candidate =
Expand Down
Loading