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

SRV implementation #5018

Open
wants to merge 31 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d1a21d4
Make Diffusion Extensible and Polymorphic
bolt12 Nov 27, 2024
d0ebe6d
diffusion: removed daExtraArgs from ArgumentsExtra
coot Feb 6, 2025
afe4866
diffusion: removed extraActions
coot Feb 6, 2025
8d62d50
diffusion: removed Applications wrapper
coot Feb 7, 2025
23a7971
diffusion: fix confused type variables
coot Feb 10, 2025
7929423
diffusion: code formatting
coot Feb 10, 2025
b0bb7e0
peer-selection: updateWithState
coot Feb 11, 2025
28cc0f0
diffusion: moved types back to the Diffusion.P2P module
coot Feb 11, 2025
d8f754d
Update CHANGELOG
bolt12 Feb 6, 2025
955a831
Add 100MB to CI memory limit
bolt12 Feb 6, 2025
05be84b
testnet: organised imports
coot Feb 12, 2025
8c9b76a
testnet: move Node module
coot Feb 12, 2025
0f22264
Increase Churn Timeout from 60 to 180s and reduced events analysed
bolt12 Feb 14, 2025
05512d2
Try to consume less memory
bolt12 Feb 14, 2025
319818e
SRV implementation
crocodile-dentist Jan 24, 2025
db55a35
rng seed for SRV dns lookups
crocodile-dentist Jan 24, 2025
89cdcae
Integrate SRV lookups with ledger peers
crocodile-dentist Jan 24, 2025
230f0aa
Integrate SRV lookups with local root peers
crocodile-dentist Jan 24, 2025
1067263
Integrate SRV lookups with public root peers
crocodile-dentist Jan 24, 2025
ce40501
Remove DomainAccessPoint
crocodile-dentist Jan 24, 2025
7c315e7
Add RelayAccessSRVDomain constructor to RelayAccessPoint type
crocodile-dentist Jan 24, 2025
12ea99e
Bump LedgerPeerSnapshot version
crocodile-dentist Jan 24, 2025
64a0049
Removes RelayAccessPointCoded and associated instances
crocodile-dentist Jan 24, 2025
1232b65
Bump LedgerPeerSnapshot tests for V2
crocodile-dentist Jan 24, 2025
fa40d6c
Rework RelayAccessPoint round trip test
crocodile-dentist Jan 24, 2025
72cb68d
PeerSelection test types and instances
crocodile-dentist Jan 24, 2025
6b4b224
PeerSelection test changes
crocodile-dentist Jan 24, 2025
93864e5
Testnet diffusion script generation refactor for SRV records
crocodile-dentist Jan 24, 2025
233789c
Testnet tests adaptations
crocodile-dentist Jan 24, 2025
3b95728
changelogs
crocodile-dentist Jan 24, 2025
0ae3f96
Remove redundant import
crocodile-dentist Feb 14, 2025
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
2 changes: 1 addition & 1 deletion cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ index-state:
, hackage.haskell.org 2024-12-10T16:20:07Z

-- Bump this if you need newer packages from CHaP
, cardano-haskell-packages 2024-09-26T15:16:07Z
, cardano-haskell-packages 2024-11-26T16:00:26Z

packages: ./cardano-ping
./monoidal-synchronisation
Expand Down
6 changes: 3 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion nix/ouroboros-network.nix
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ let
preCheck =
lib.mkForce
(if buildSystem == "x86_64-linux"
then "export GHCRTS=-M300M"
then "export GHCRTS=-M500M"
else "");
doCheck = !pkgs.stdenv.hostPlatform.isWindows;

Expand Down
14 changes: 14 additions & 0 deletions ouroboros-network-api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@
### Breaking changes

* Added `NodeToClientV_20`.
- Moved `Ouroboros.Network.ConsensusMode` to `Cardano.Network.ConsensusMode`
- Moved `Ouroboros.Network.PeerSelection.Bootstrap` to `Cardano.Network.PeerSelection.Bootstrap`
- Moved `Ouroboros.Network.PeerSelection.LocalRootPeers` to `Cardano.Network.PeerSelection.LocalRootPeers`
- Moved `Ouroboros.Network.PeerSelection.PeerTrustable` to `Cardano.Network.PeerSelection.PeerTrustable`
- Created `Cardano.Network.Types` and moved Cardano specific types such as
`LedgerStateJudgement` and `NumberOfBigLedgerPeers` from
`Ouroboros.Network.PeerSelection.LedgerPeers/Type` to there.
- Removed `lpGetLedgerStateJudgment` from `LedgerConsensusInterface` and added
`extraAPI` type parameter to it.
* Removed `DomainAccessPoint` type
* Added `RelayAccessSRVDomain` tag to `RelayAccessPoint`
* Removed `RelayAccessPointCoded` type
* Bumped LedgerPeerSnapshot version to 2 to directly
leverage JSON and CBOR instances for `RelayAccessPoint`

### Non-breaking changes

Expand Down
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.Network.ConsensusMode
Cardano.Network.PeerSelection.Bootstrap
Cardano.Network.PeerSelection.LocalRootPeers
Cardano.Network.PeerSelection.PeerTrustable
Cardano.Network.Types
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.Network.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.Network.PeerSelection.Bootstrap
( UseBootstrapPeers (..)
, isBootstrapPeersEnabled
, requiresBootstrapPeers
, isNodeAbleToMakeProgress
) where

import Cardano.Network.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.Network.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.Network.PeerSelection.PeerTrustable (PeerTrustable (..)) where

import GHC.Generics (Generic)

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

module Cardano.Network.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 NumberOfBigLedgerPeers =
NumberOfBigLedgerPeers { getNumberOfBigLedgerPeers :: Int }
deriving stock (Eq, Show)
deriving newtype (FromJSON)

Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@ import GHC.Generics (Generic)
import GHC.Stack (HasCallStack)
import NoThunks.Class (NoThunks)

import Cardano.Network.ConsensusMode (ConsensusMode (..))
import Cardano.Network.Types (LedgerStateJudgement (..))
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)

data PraosFetchMode =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingVia #-}
Expand All @@ -18,53 +19,36 @@ module Ouroboros.Network.PeerSelection.LedgerPeers.Type
( PoolStake (..)
, AccPoolStake (..)
, IsBigLedgerPeer (..)
, LedgerStateJudgement (..)
, LedgerPeersConsensusInterface (..)
, mapExtraAPI
, UseLedgerPeers (..)
, AfterSlot (..)
, LedgerPeersKind (..)
, LedgerPeerSnapshot (.., LedgerPeerSnapshot)
, MinBigLedgerPeersForTrustedState (..)
, isLedgerPeersEnabled
, compareLedgerPeerSnapshotApproximate
) where

import Control.Monad (forM)
import Data.ByteString.Char8 qualified as BS
import Data.List.NonEmpty (NonEmpty)
import Data.Text.Encoding (decodeUtf8)
import GHC.Generics (Generic)
import Text.Read (readMaybe)

import Cardano.Binary (FromCBOR (..), ToCBOR (..))
import Cardano.Binary qualified as Codec
import Cardano.Slotting.Slot (SlotNo (..), WithOrigin (..))
import Control.Concurrent.Class.MonadSTM
import Control.DeepSeq (NFData (..))
import Control.Monad (forM)
import Data.Aeson
import Data.Aeson.Types
import Data.List.NonEmpty (NonEmpty)
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)
import Ouroboros.Network.PeerSelection.RelayAccessPoint

-- |The type of big ledger peers that is serialised or later
-- provided by node configuration for the networking layer
-- to connect to when syncing.
--
data LedgerPeerSnapshot =
LedgerPeerSnapshotV1 (WithOrigin SlotNo, [(AccPoolStake, (PoolStake, NonEmpty RelayAccessPoint))])
LedgerPeerSnapshotV2 (WithOrigin SlotNo, [(AccPoolStake, (PoolStake, NonEmpty RelayAccessPoint))])
-- ^ Internal use for version 1, use pattern synonym for public API
deriving (Eq, Show)

Expand All @@ -74,8 +58,8 @@ data LedgerPeerSnapshot =
--
pattern LedgerPeerSnapshot :: (WithOrigin SlotNo, [(AccPoolStake, (PoolStake, NonEmpty RelayAccessPoint))])
-> LedgerPeerSnapshot
pattern LedgerPeerSnapshot payload <- LedgerPeerSnapshotV1 payload where
LedgerPeerSnapshot payload = LedgerPeerSnapshotV1 payload
pattern LedgerPeerSnapshot payload <- LedgerPeerSnapshotV2 payload where
LedgerPeerSnapshot payload = LedgerPeerSnapshotV2 payload

{-# COMPLETE LedgerPeerSnapshot #-}

Expand Down Expand Up @@ -104,33 +88,36 @@ compareLedgerPeerSnapshotApproximate baseline candidate =
--
migrateLedgerPeerSnapshot :: LedgerPeerSnapshot
-> Maybe (WithOrigin SlotNo, [(AccPoolStake, (PoolStake, NonEmpty RelayAccessPoint))])
migrateLedgerPeerSnapshot (LedgerPeerSnapshotV1 lps) = Just lps
migrateLedgerPeerSnapshot (LedgerPeerSnapshotV2 lps) = Just lps

instance ToJSON LedgerPeerSnapshot where
toJSON (LedgerPeerSnapshotV1 (slot, pools)) =
object [ "version" .= (1 :: Int)
toJSON (LedgerPeerSnapshotV2 (slot, pools)) =
object [ "version" .= (2 :: Int)
, "slotNo" .= slot
, "bigLedgerPools" .= [ object [ "accumulatedStake" .= fromRational @Double accStake
, "relativeStake" .= fromRational @Double relStake
, "relays" .= relays']
| (AccPoolStake accStake, (PoolStake relStake, relays)) <- pools
, let relays' = fmap RelayAccessPointCoded relays]]
, "bigLedgerPools" .= [ object
[ "accumulatedStake" .= fromRational @Double accStake
, "relativeStake" .= fromRational @Double relStake
, "relays" .= relays]
| (AccPoolStake accStake, (PoolStake relStake, relays)) <- pools
]]

instance FromJSON LedgerPeerSnapshot where
parseJSON = withObject "LedgerPeerSnapshot" $ \v -> do
vNum :: Int <- v .: "version"
parsedSnapshot <-
case vNum of
1 -> do
2 -> do
slot <- v .: "slotNo"
bigPools <- v .: "bigLedgerPools"
bigPools' <- (forM bigPools . withObject "bigLedgerPools" $ \poolV -> do
AccPoolStakeCoded accStake <- poolV .: "accumulatedStake"
PoolStakeCoded reStake <- poolV .: "relativeStake"
relays <- fmap unRelayAccessPointCoded <$> poolV .: "relays"
return (accStake, (reStake, relays))) <?> Key "bigLedgerPools"

return $ LedgerPeerSnapshotV1 (slot, bigPools')
bigPools' <- forM (zip [0 :: Int ..] bigPools) \(idx, poolO) -> do
let f poolV = do
AccPoolStakeCoded accStake <- poolV .: "accumulatedStake"
PoolStakeCoded reStake <- poolV .: "relativeStake"
relays <- poolV .: "relays"
return (accStake, (reStake, relays))
withObject ("bigLedgerPools[" <> show idx <> "]") f (Object poolO)

return $ LedgerPeerSnapshotV2 (slot, bigPools')
_ -> fail $ "Network.LedgerPeers.Type: parseJSON: failed to parse unsupported version " <> show vNum
case migrateLedgerPeerSnapshot parsedSnapshot of
Just payload -> return $ LedgerPeerSnapshot payload
Expand Down Expand Up @@ -160,26 +147,26 @@ instance FromCBOR WithOriginCoded where
_ -> fail "LedgerPeers.Type: Unrecognized list length while decoding WithOrigin SlotNo"

instance ToCBOR LedgerPeerSnapshot where
toCBOR (LedgerPeerSnapshotV1 (wOrigin, pools)) =
toCBOR (LedgerPeerSnapshotV2 (wOrigin, pools)) =
Codec.encodeListLen 2
<> Codec.encodeWord8 1
<> Codec.encodeWord8 2
<> toCBOR (WithOriginCoded wOrigin, pools')
where
pools' =
[(AccPoolStakeCoded accPoolStake, (PoolStakeCoded relStake, neRelayAccessPointCoded))
[(AccPoolStakeCoded accPoolStake, (PoolStakeCoded relStake, relays))
| (accPoolStake, (relStake, relays)) <- pools
, let neRelayAccessPointCoded = fmap RelayAccessPointCoded relays]
]

instance FromCBOR LedgerPeerSnapshot where
fromCBOR = do
Codec.decodeListLenOf 2
version <- Codec.decodeWord8
case version of
1 -> LedgerPeerSnapshotV1 <$> do
2 -> LedgerPeerSnapshotV2 <$> do
(WithOriginCoded wOrigin, pools) <- fromCBOR
let pools' = [(accStake, (relStake, relays'))
let pools' = [(accStake, (relStake, relays))
| (AccPoolStakeCoded accStake, (PoolStakeCoded relStake, relays)) <- pools
, let relays' = unRelayAccessPointCoded <$> relays]
]
return (wOrigin, pools')
_ -> fail $ "LedgerPeers.Type: no decoder could be found for version " <> show version

Expand Down Expand Up @@ -237,45 +224,15 @@ 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 {
lpGetLatestSlot :: STM m (WithOrigin SlotNo),
lpGetLedgerStateJudgement :: STM m LedgerStateJudgement,
lpGetLedgerPeers :: STM m [(PoolStake, NonEmpty RelayAccessPoint)]
data LedgerPeersConsensusInterface extraAPI m = LedgerPeersConsensusInterface {
lpGetLatestSlot :: STM m (WithOrigin SlotNo)
, lpGetLedgerPeers :: STM m [(PoolStake, NonEmpty RelayAccessPoint)]
-- | Extension point so that third party users can add more actions
, lpExtraAPI :: extraAPI
}

instance ToJSON RelayAccessPointCoded where
toJSON (RelayAccessPointCoded (RelayAccessDomain domain port)) =
object
[ "domain" .= decodeUtf8 domain
, "port" .= (fromIntegral port :: Int)]

toJSON (RelayAccessPointCoded (RelayAccessAddress ip port)) =
object
[ "address" .= show ip
, "port" .= (fromIntegral port :: Int)]

instance FromJSON RelayAccessPointCoded where
parseJSON = withObject "RelayAccessPointCoded" $ \v -> do
domain <- fmap BS.pack <$> v .:? "domain"
port <- fromIntegral @Int <$> v .: "port"
case domain of
Nothing ->
v .: "address"
>>= \case
Nothing -> fail "RelayAccessPointCoded: invalid IP address"
Just addr ->
return . RelayAccessPointCoded $ RelayAccessAddress addr port
. readMaybe

Just domain'
| Just (_, '.') <- BS.unsnoc domain' ->
return . RelayAccessPointCoded $ RelayAccessDomain domain' port
| otherwise ->
let fullyQualified = domain' `BS.snoc` '.'
in return . RelayAccessPointCoded $ RelayAccessDomain fullyQualified port
mapExtraAPI :: (a -> b) -> LedgerPeersConsensusInterface a m -> LedgerPeersConsensusInterface b m
mapExtraAPI f lpci@LedgerPeersConsensusInterface{ lpExtraAPI = api } =
lpci { lpExtraAPI = f api }
Loading
Loading