Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reusable Diffusion - Make diffusion fully polymorphic #5016

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
9 changes: 5 additions & 4 deletions ouroboros-network-api/ouroboros-network-api.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,29 @@ flag asserts
library
hs-source-dirs: src
exposed-modules:
Cardano.Node.ConsensusMode
Cardano.Node.PeerSelection.Bootstrap
Cardano.Node.PeerSelection.LocalRootPeers
Cardano.Node.PeerSelection.PeerTrustable
Cardano.Node.Types
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check what consensus uses.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What did you decide to use?

Ouroboros.Network.AnchoredFragment
Ouroboros.Network.AnchoredSeq
Ouroboros.Network.Block
Ouroboros.Network.BlockFetch.ConsensusInterface
Ouroboros.Network.CodecCBORTerm
Ouroboros.Network.ConsensusMode
Ouroboros.Network.ControlMessage
Ouroboros.Network.Handshake
Ouroboros.Network.Handshake.Acceptable
Ouroboros.Network.Handshake.Queryable
Ouroboros.Network.Magic
Ouroboros.Network.NodeToClient.Version
Ouroboros.Network.NodeToNode.Version
Ouroboros.Network.PeerSelection.Bootstrap
Ouroboros.Network.PeerSelection.LedgerPeers.Type
Ouroboros.Network.PeerSelection.LedgerPeers.Utils
Ouroboros.Network.PeerSelection.LocalRootPeers
Ouroboros.Network.PeerSelection.PeerAdvertise
Ouroboros.Network.PeerSelection.PeerMetric.Type
Ouroboros.Network.PeerSelection.PeerSharing
Ouroboros.Network.PeerSelection.PeerSharing.Codec
Ouroboros.Network.PeerSelection.PeerTrustable
Ouroboros.Network.PeerSelection.RelayAccessPoint
Ouroboros.Network.Point
Ouroboros.Network.Protocol.Limits
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}

module Ouroboros.Network.ConsensusMode where
module Cardano.Node.ConsensusMode where

import Data.Aeson
import GHC.Generics (Generic)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}

module Ouroboros.Network.PeerSelection.Bootstrap
module Cardano.Node.PeerSelection.Bootstrap
( UseBootstrapPeers (..)
, isBootstrapPeersEnabled
, requiresBootstrapPeers
, isNodeAbleToMakeProgress
) where

import Cardano.Node.Types (LedgerStateJudgement (..))
import GHC.Generics (Generic)
import Ouroboros.Network.PeerSelection.LedgerPeers.Type
(LedgerStateJudgement (..))
import Ouroboros.Network.PeerSelection.RelayAccessPoint (RelayAccessPoint)

data UseBootstrapPeers = DontUseBootstrapPeers
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{-# LANGUAGE DeriveGeneric #-}

module Ouroboros.Network.PeerSelection.LocalRootPeers (OutboundConnectionsState (..)) where
module Cardano.Node.PeerSelection.LocalRootPeers (OutboundConnectionsState (..)) where

import GHC.Generics
import NoThunks.Class
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{-# LANGUAGE DeriveGeneric #-}

module Ouroboros.Network.PeerSelection.PeerTrustable (PeerTrustable (..)) where
module Cardano.Node.PeerSelection.PeerTrustable (PeerTrustable (..)) where

import GHC.Generics (Generic)

Expand Down
29 changes: 29 additions & 0 deletions ouroboros-network-api/src/Cardano/Node/Types.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Cardano.Node.Types where

import Data.Aeson (FromJSON)
import GHC.Generics (Generic)
import NoThunks.Class (NoThunks)

-- | Wether the node is caught up or fell too far behind the chain
data LedgerStateJudgement = YoungEnough | TooOld
deriving (Eq, Show, Generic)

instance NoThunks LedgerStateJudgement

-- | Minimum number of hot big ledger peers in Genesis mode
-- for trusted state to be signalled to Consensus. This number
-- should be smaller than the `targetNumberOfActiveBigLedgerPeers`
-- but greater than 1. In Genesis, we may demote a big ledger peer
-- for underperformance, but not promote a replacement immediately
-- to guard against adversaries which may want to slow down our
-- progress.
--
newtype MinBigLedgerPeersForTrustedState =
MinBigLedgerPeersForTrustedState { getMinBigLedgerPeersForTrustedState :: Int }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
newtype MinBigLedgerPeersForTrustedState =
MinBigLedgerPeersForTrustedState { getMinBigLedgerPeersForTrustedState :: Int }
newtype NumberOfBigLedgerPeers =
NumberOfBigLedgerPeers { getNumberOfBigLedgerPeers :: Int }

the rest is explained in the haddock.

deriving stock (Eq, Show)
deriving newtype (FromJSON)

Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@ import NoThunks.Class (NoThunks)

import Ouroboros.Network.AnchoredFragment (AnchoredFragment)
import Ouroboros.Network.Block
import Ouroboros.Network.ConsensusMode (ConsensusMode (..))
import Ouroboros.Network.PeerSelection.LedgerPeers.Type
(LedgerStateJudgement (..))
import Ouroboros.Network.SizeInBytes (SizeInBytes)
import Cardano.Node.ConsensusMode (ConsensusMode (..))
import Cardano.Node.Types (LedgerStateJudgement (..))

data PraosFetchMode =
-- | Use this mode when we are catching up on the chain but are stil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@ module Ouroboros.Network.PeerSelection.LedgerPeers.Type
( PoolStake (..)
, AccPoolStake (..)
, IsBigLedgerPeer (..)
, LedgerStateJudgement (..)
, LedgerPeersConsensusInterface (..)
, UseLedgerPeers (..)
, AfterSlot (..)
, LedgerPeersKind (..)
, LedgerPeerSnapshot (.., LedgerPeerSnapshot)
, MinBigLedgerPeersForTrustedState (..)
, isLedgerPeersEnabled
, compareLedgerPeerSnapshotApproximate
) where
Expand All @@ -38,6 +36,7 @@ import Text.Read (readMaybe)

import Cardano.Binary (FromCBOR (..), ToCBOR (..))
import Cardano.Binary qualified as Codec
import Cardano.Node.Types (LedgerStateJudgement)
import Cardano.Slotting.Slot (SlotNo (..), WithOrigin (..))
import Control.Concurrent.Class.MonadSTM
import Control.DeepSeq (NFData (..))
Expand All @@ -46,19 +45,6 @@ import Data.Aeson.Types
import NoThunks.Class
import Ouroboros.Network.PeerSelection.RelayAccessPoint

-- | Minimum number of hot big ledger peers in Genesis mode
-- for trusted state to be signalled to Consensus. This number
-- should be smaller than the `targetNumberOfActiveBigLedgerPeers`
-- but greater than 1. In Genesis, we may demote a big ledger peer
-- for underperformance, but not promote a replacement immediately
-- to guard against adversaries which may want to slow down our
-- progress.
--
newtype MinBigLedgerPeersForTrustedState =
MinBigLedgerPeersForTrustedState { getMinBigLedgerPeersForTrustedState :: Int }
deriving stock (Eq, Show)
deriving newtype (FromJSON)

-- |The type of big ledger peers that is serialised or later
-- provided by node configuration for the networking layer
-- to connect to when syncing.
Expand Down Expand Up @@ -237,10 +223,6 @@ data IsBigLedgerPeer
| IsNotBigLedgerPeer
deriving Eq

-- | Wether the node is caught up or fell too far behind the chain
data LedgerStateJudgement = YoungEnough | TooOld
deriving (Eq, Show, Generic, NoThunks)

-- | Return ledger state information and ledger peers.
--
data LedgerPeersConsensusInterface m = LedgerPeersConsensusInterface {
Expand Down
7 changes: 7 additions & 0 deletions ouroboros-network/ouroboros-network.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ library
-- At this experiment/prototype stage everything is exposed.
-- This has to be tidied up once the design becomes clear.
exposed-modules:
Cardano.Node.ArgumentsExtra
Cardano.Node.LedgerPeerConsensusInterface
Cardano.Node.PeerSelection.Governor.PeerSelectionActions
Cardano.Node.PeerSelection.Governor.PeerSelectionState
Cardano.Node.PeerSelection.PeerChurnArgs
Cardano.Node.PeerSelection.Types
Cardano.Node.PublicRootPeers
bolt12 marked this conversation as resolved.
Show resolved Hide resolved
Control.Concurrent.Class.MonadSTM.Strict.TMergeVar
Ouroboros.Network.BlockFetch
Ouroboros.Network.BlockFetch.Client
Expand Down
37 changes: 37 additions & 0 deletions ouroboros-network/src/Cardano/Node/ArgumentsExtra.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module Cardano.Node.ArgumentsExtra where

import Cardano.Node.ConsensusMode (ConsensusMode)
import Cardano.Node.PeerSelection.Bootstrap (UseBootstrapPeers)
import Cardano.Node.Types (MinBigLedgerPeersForTrustedState)
import Control.Concurrent.Class.MonadSTM (MonadSTM (..))
import Ouroboros.Network.PeerSelection.Governor.Types
(PeerSelectionTargets (..))

-- | Cardano Node specific (extra) arguments to be passed to diffusion.
--
data CardanoArgumentsExtra m =
CardanoArgumentsExtra {
-- | selection targets for the peer governor
caePeerTargets :: ConsensusModePeerTargets
, caeReadUseBootstrapPeers :: STM m UseBootstrapPeers

-- | For Genesis, this sets the floor for minimum number of
-- active big ledger peers we must be connected to in order
-- to be able to signal trusted state (OutboundConnectionsState)
, caeMinBigLedgerPeersForTrustedState :: MinBigLedgerPeersForTrustedState
-- | When syncing up, ie. ledgerStateJudgement == TooOld,
-- when this is True we will maintain connection with many big ledger peers
-- to get a strong guarantee that when syncing up we will finish with a true
-- ledger state. When false, we will fall back on the previous algorithms
-- that leverage UseBootstrapPeers flag
, caeConsensusMode :: ConsensusMode
}

-- | Provides alternate peer selection targets
-- for various syncing modes.
--
data ConsensusModePeerTargets = ConsensusModePeerTargets {
deadlineTargets :: !PeerSelectionTargets,
syncTargets :: !PeerSelectionTargets
}
deriving (Eq, Show)
21 changes: 21 additions & 0 deletions ouroboros-network/src/Cardano/Node/LedgerPeerConsensusInterface.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module Cardano.Node.LedgerPeerConsensusInterface where

import Cardano.Node.PeerSelection.LocalRootPeers (OutboundConnectionsState)
import Cardano.Node.Types (LedgerStateJudgement)
import Control.Concurrent.Class.MonadSTM (MonadSTM (..))

-- | Cardano Node specific consensus interface actions.
--
data CardanoLedgerPeersConsensusInterface m =
CardanoLedgerPeersConsensusInterface {
clpciGetLedgerStateJudgement :: STM m LedgerStateJudgement

-- | Callback provided by consensus to inform it if the node is
-- connected to only local roots or also some external peers.
--
-- This is useful in order for the Bootstrap State Machine to
-- simply refuse to transition from TooOld to YoungEnough while
-- it only has local peers.
--
, clpciUpdateOutboundConnectionsState :: OutboundConnectionsState -> STM m ()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module Cardano.Node.PeerSelection.Governor.PeerSelectionActions where

import Cardano.Node.ArgumentsExtra (ConsensusModePeerTargets)
import Cardano.Node.PeerSelection.Bootstrap (UseBootstrapPeers)
import Control.Concurrent.Class.MonadSTM

-- | Cardano Node PeerSelection Actions extension data type.
--
-- It contain specific PeerSelection actions parameters to guide the Outbound
-- Governor.
--
data CardanoPeerSelectionActions m =
CardanoPeerSelectionActions {
-- | Retrieve peer targets for Genesis & non-Genesis modes
-- from node's configuration for the current state
--
cpsaPeerTargets :: ConsensusModePeerTargets

-- | Read the current bootstrap peers flag
, cpsaReadUseBootstrapPeers :: STM m UseBootstrapPeers
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
module Cardano.Node.PeerSelection.Governor.PeerSelectionState where

import Cardano.Node.ConsensusMode (ConsensusMode)
import Cardano.Node.PeerSelection.Bootstrap (UseBootstrapPeers (..))
import Cardano.Node.Types (LedgerStateJudgement (..),
MinBigLedgerPeersForTrustedState (..))
import Control.Monad.Class.MonadTime.SI (Time)

-- | Cardano Node PeerSelection State extension data type.
-- It contain specific PeerSelection state parameters to guide the Outbound
-- Governor.
--
data CardanoPeerSelectionState =
CardanoPeerSelectionState {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd call this CardanoExtraState and then we can have & use

type CardanoPeerSelectionState = PeerSelectionState CardanoExtraState ...

ref: bae4f75

-- | Current ledger state judgement
cpstLedgerStateJudgement :: !LedgerStateJudgement
-- | Flag whether to sync in genesis mode when ledgerStateJudgement == TooOld
-- this comes from node configuration and should be treated as read-only
--
, cpstConsensusMode :: !ConsensusMode
-- | Current value of 'UseBootstrapPeers'.
--
, cpstBootstrapPeersFlag :: !UseBootstrapPeers
-- | Has the governor fully reset its state
--
, cpstHasOnlyBootstrapPeers :: !Bool
-- | Has the governor fully reset its state
--
, cpstBootstrapPeersTimeout :: !(Maybe Time)
-- | Use in Genesis mode to check whether we can signal to
-- consensus that we met criteria of trusted state to enter
-- deadline mode. This parameter comes from node configuration,
-- with a default value in the `Configuration` module.
--
, cpstMinBigLedgerPeersForTrustedState :: MinBigLedgerPeersForTrustedState
}
deriving Show

empty :: ConsensusMode -> MinBigLedgerPeersForTrustedState -> CardanoPeerSelectionState
empty consensusMode minActiveBigLedgerPeers =
CardanoPeerSelectionState {
cpstLedgerStateJudgement = TooOld,
cpstConsensusMode = consensusMode,
cpstBootstrapPeersFlag = DontUseBootstrapPeers,
cpstHasOnlyBootstrapPeers = False,
cpstBootstrapPeersTimeout = Nothing,
cpstMinBigLedgerPeersForTrustedState = minActiveBigLedgerPeers
}

data CardanoDebugPeerSelectionState =
CardanoDebugPeerSelectionState {
cdpssLedgerStateJudgement :: !LedgerStateJudgement
}
deriving Show

18 changes: 18 additions & 0 deletions ouroboros-network/src/Cardano/Node/PeerSelection/PeerChurnArgs.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module Cardano.Node.PeerSelection.PeerChurnArgs where

import Cardano.Node.ArgumentsExtra (ConsensusModePeerTargets)
import Cardano.Node.ConsensusMode (ConsensusMode)
import Cardano.Node.PeerSelection.Bootstrap (UseBootstrapPeers)
import Cardano.Node.PeerSelection.Types (ChurnMode)
import Control.Concurrent.Class.MonadSTM.Strict
import Ouroboros.Network.BlockFetch.ConsensusInterface (FetchMode)

data CardanoPeerChurnArgs m =
CardanoPeerChurnArgs {
cpcaModeVar :: StrictTVar m ChurnMode
, cpcaReadFetchMode :: STM m FetchMode
, cpcaPeerTargets :: ConsensusModePeerTargets
, cpcaReadUseBootstrap :: STM m UseBootstrapPeers
, cpcaConsensusMode :: ConsensusMode
}

6 changes: 6 additions & 0 deletions ouroboros-network/src/Cardano/Node/PeerSelection/Types.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module Cardano.Node.PeerSelection.Types where

data ChurnMode = ChurnModeBulkSync
| ChurnModeNormal
deriving Show

45 changes: 45 additions & 0 deletions ouroboros-network/src/Cardano/Node/PublicRootPeers.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{-# LANGUAGE NamedFieldPuns #-}

module Cardano.Node.PublicRootPeers where

import Data.Map.Strict (Map)
import Data.Map.Strict qualified as Map
import Data.Set (Set)
import Data.Set qualified as Set
import Data.Typeable (Typeable)
import Ouroboros.Network.PeerSelection.PeerAdvertise (PeerAdvertise)

data CardanoPublicRootPeers peeraddr =
CardanoPublicRootPeers
{ cprpGetPublicConfigPeers :: !(Map peeraddr PeerAdvertise)
, cprpGetBootstrapPeers :: !(Set peeraddr)
}
deriving (Eq, Show, Typeable)
bolt12 marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type should be called CardanoExtraPeers, and then we could provide & use the following:

type CardanoPublicRootPeers peeraddr = PublicRootPeers (CardanoExtraPeers peeraddr) peeraddr 

ref: bae4f75


instance Ord peeraddr => Semigroup (CardanoPublicRootPeers peeraddr) where
(CardanoPublicRootPeers a b) <> (CardanoPublicRootPeers a' b') =
let -- Combine the sets, prioritizing bootstrapPeers
combinedSet = b `Set.union` b'
-- Combine the maps and remove any peers that are now in the set
combinedMap = (a `Map.union` a') `Map.withoutKeys` combinedSet
in CardanoPublicRootPeers combinedMap combinedSet

instance Ord peeraddr => Monoid (CardanoPublicRootPeers peeraddr) where
mempty = empty

-- Map and Set are disjoint
--
invariant :: Ord peeraddr => CardanoPublicRootPeers peeraddr -> Bool
invariant (CardanoPublicRootPeers a b) = all (`Map.notMember` a) b

empty :: CardanoPublicRootPeers peeraddr
empty = CardanoPublicRootPeers Map.empty Set.empty

nullPublicConfig :: CardanoPublicRootPeers peeraddr -> Bool
nullPublicConfig CardanoPublicRootPeers { cprpGetPublicConfigPeers } =
Map.null cprpGetPublicConfigPeers

nullBootstrap :: CardanoPublicRootPeers peeraddr -> Bool
nullBootstrap CardanoPublicRootPeers { cprpGetBootstrapPeers } =
Set.null cprpGetBootstrapPeers

Loading