{-# LANGUAGE DerivingVia    #-}
{-# LANGUAGE NamedFieldPuns #-}

module Ouroboros.Network.PeerSelection.PublicRootPeers
  ( -- * Types
    PublicRootPeers (..)
    -- Export constructors for defining tests.
  , invariant
    -- * Basic operations
  , empty
  , null
  , size
  , member
  , merge
  , difference
  , intersection
  , toSet
  , toPublicConfigPeerSet
  , toAllLedgerPeerSet
  , insertPublicConfigPeer
  , insertBootstrapPeer
  , insertLedgerPeer
  , insertBigLedgerPeer
  , fromPublicRootPeers
  , fromBootstrapPeers
  , fromLedgerPeers
  , fromBigLedgerPeers
  , fromMapAndSet
  ) where

import Prelude hiding (null)

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

---------------------------------------
-- Public root peer set representation
--
-- This data type is useful to abstract several public root peer sources into
-- one type. This helps cleaning up the code and centralizing everything under
-- a nice API.

-- | Public Root Peers consist of either a set of manually configured
-- bootstrap peers.
--
-- There's an implicit precedence that will priorise bootstrap peers over the
-- other sets, so if we are adding a bootstrap peer and that peer is already a
-- member of other public root set, it is going to be removed from that set
-- and added to the bootstrap peer set.
--
data PublicRootPeers peeraddr =
  PublicRootPeers { forall peeraddr.
PublicRootPeers peeraddr -> Map peeraddr PeerAdvertise
getPublicConfigPeers :: !(Map peeraddr PeerAdvertise)
                  , forall peeraddr. PublicRootPeers peeraddr -> Set peeraddr
getBootstrapPeers    :: !(Set peeraddr)
                  , forall peeraddr. PublicRootPeers peeraddr -> Set peeraddr
getLedgerPeers       :: !(Set peeraddr)
                  , forall peeraddr. PublicRootPeers peeraddr -> Set peeraddr
getBigLedgerPeers    :: !(Set peeraddr)
                  }
  deriving (PublicRootPeers peeraddr -> PublicRootPeers peeraddr -> Bool
(PublicRootPeers peeraddr -> PublicRootPeers peeraddr -> Bool)
-> (PublicRootPeers peeraddr -> PublicRootPeers peeraddr -> Bool)
-> Eq (PublicRootPeers peeraddr)
forall peeraddr.
Eq peeraddr =>
PublicRootPeers peeraddr -> PublicRootPeers peeraddr -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall peeraddr.
Eq peeraddr =>
PublicRootPeers peeraddr -> PublicRootPeers peeraddr -> Bool
== :: PublicRootPeers peeraddr -> PublicRootPeers peeraddr -> Bool
$c/= :: forall peeraddr.
Eq peeraddr =>
PublicRootPeers peeraddr -> PublicRootPeers peeraddr -> Bool
/= :: PublicRootPeers peeraddr -> PublicRootPeers peeraddr -> Bool
Eq, Int -> PublicRootPeers peeraddr -> ShowS
[PublicRootPeers peeraddr] -> ShowS
PublicRootPeers peeraddr -> String
(Int -> PublicRootPeers peeraddr -> ShowS)
-> (PublicRootPeers peeraddr -> String)
-> ([PublicRootPeers peeraddr] -> ShowS)
-> Show (PublicRootPeers peeraddr)
forall peeraddr.
Show peeraddr =>
Int -> PublicRootPeers peeraddr -> ShowS
forall peeraddr.
Show peeraddr =>
[PublicRootPeers peeraddr] -> ShowS
forall peeraddr.
Show peeraddr =>
PublicRootPeers peeraddr -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall peeraddr.
Show peeraddr =>
Int -> PublicRootPeers peeraddr -> ShowS
showsPrec :: Int -> PublicRootPeers peeraddr -> ShowS
$cshow :: forall peeraddr.
Show peeraddr =>
PublicRootPeers peeraddr -> String
show :: PublicRootPeers peeraddr -> String
$cshowList :: forall peeraddr.
Show peeraddr =>
[PublicRootPeers peeraddr] -> ShowS
showList :: [PublicRootPeers peeraddr] -> ShowS
Show)

invariant :: Ord peeraddr => PublicRootPeers peeraddr -> Bool
invariant :: forall peeraddr. Ord peeraddr => PublicRootPeers peeraddr -> Bool
invariant (PublicRootPeers Map peeraddr PeerAdvertise
pp Set peeraddr
bsp Set peeraddr
lp Set peeraddr
blp) =
     -- bootstrap peers and ledger peers should not overlap
     Set peeraddr -> Bool
forall a. Set a -> Bool
Set.null (Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Ord a => Set a -> Set a -> Set a
Set.intersection Set peeraddr
bsp Set peeraddr
lp)
     -- bootstrap peers and big ledger peers should not overlap
  Bool -> Bool -> Bool
&& Set peeraddr -> Bool
forall a. Set a -> Bool
Set.null (Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Ord a => Set a -> Set a -> Set a
Set.intersection Set peeraddr
bsp Set peeraddr
blp)
     -- bootstrap peers and public config peers should not overlap
  Bool -> Bool -> Bool
&& Set peeraddr -> Bool
forall a. Set a -> Bool
Set.null (Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Ord a => Set a -> Set a -> Set a
Set.intersection Set peeraddr
bsp (Map peeraddr PeerAdvertise -> Set peeraddr
forall k a. Map k a -> Set k
Map.keysSet Map peeraddr PeerAdvertise
pp))
    -- ledger and big ledger peers should not overlap
  Bool -> Bool -> Bool
&& Set peeraddr -> Bool
forall a. Set a -> Bool
Set.null (Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Ord a => Set a -> Set a -> Set a
Set.intersection Set peeraddr
lp Set peeraddr
blp)
    -- ledger peers and public config peers should not overlap
  Bool -> Bool -> Bool
&& Set peeraddr -> Bool
forall a. Set a -> Bool
Set.null (Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Ord a => Set a -> Set a -> Set a
Set.intersection Set peeraddr
lp (Map peeraddr PeerAdvertise -> Set peeraddr
forall k a. Map k a -> Set k
Map.keysSet Map peeraddr PeerAdvertise
pp))
    -- big ledger peers and public config peers should not overlap
  Bool -> Bool -> Bool
&& Set peeraddr -> Bool
forall a. Set a -> Bool
Set.null (Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Ord a => Set a -> Set a -> Set a
Set.intersection Set peeraddr
blp (Map peeraddr PeerAdvertise -> Set peeraddr
forall k a. Map k a -> Set k
Map.keysSet Map peeraddr PeerAdvertise
pp))

empty :: PublicRootPeers peeraddr
empty :: forall peeraddr. PublicRootPeers peeraddr
empty = Map peeraddr PeerAdvertise
-> Set peeraddr
-> Set peeraddr
-> Set peeraddr
-> PublicRootPeers peeraddr
forall peeraddr.
Map peeraddr PeerAdvertise
-> Set peeraddr
-> Set peeraddr
-> Set peeraddr
-> PublicRootPeers peeraddr
PublicRootPeers Map peeraddr PeerAdvertise
forall k a. Map k a
Map.empty Set peeraddr
forall a. Set a
Set.empty Set peeraddr
forall a. Set a
Set.empty Set peeraddr
forall a. Set a
Set.empty

nullPublicConfig :: PublicRootPeers peeraddr -> Bool
nullPublicConfig :: forall peeraddr. PublicRootPeers peeraddr -> Bool
nullPublicConfig PublicRootPeers { Map peeraddr PeerAdvertise
getPublicConfigPeers :: forall peeraddr.
PublicRootPeers peeraddr -> Map peeraddr PeerAdvertise
getPublicConfigPeers :: Map peeraddr PeerAdvertise
getPublicConfigPeers } =
  Map peeraddr PeerAdvertise -> Bool
forall k a. Map k a -> Bool
Map.null Map peeraddr PeerAdvertise
getPublicConfigPeers

nullBootstrap :: PublicRootPeers peeraddr -> Bool
nullBootstrap :: forall peeraddr. PublicRootPeers peeraddr -> Bool
nullBootstrap PublicRootPeers { Set peeraddr
getBootstrapPeers :: forall peeraddr. PublicRootPeers peeraddr -> Set peeraddr
getBootstrapPeers :: Set peeraddr
getBootstrapPeers } =
  Set peeraddr -> Bool
forall a. Set a -> Bool
Set.null Set peeraddr
getBootstrapPeers

nullLedgerPeers :: PublicRootPeers peeraddr -> Bool
nullLedgerPeers :: forall peeraddr. PublicRootPeers peeraddr -> Bool
nullLedgerPeers PublicRootPeers { Set peeraddr
getLedgerPeers :: forall peeraddr. PublicRootPeers peeraddr -> Set peeraddr
getLedgerPeers :: Set peeraddr
getLedgerPeers } =
  Set peeraddr -> Bool
forall a. Set a -> Bool
Set.null Set peeraddr
getLedgerPeers

nullBigLedgerPeers :: PublicRootPeers peeraddr -> Bool
nullBigLedgerPeers :: forall peeraddr. PublicRootPeers peeraddr -> Bool
nullBigLedgerPeers PublicRootPeers { Set peeraddr
getBigLedgerPeers :: forall peeraddr. PublicRootPeers peeraddr -> Set peeraddr
getBigLedgerPeers :: Set peeraddr
getBigLedgerPeers } =
  Set peeraddr -> Bool
forall a. Set a -> Bool
Set.null Set peeraddr
getBigLedgerPeers

nullAllLedgerPeers :: PublicRootPeers peeraddr -> Bool
nullAllLedgerPeers :: forall peeraddr. PublicRootPeers peeraddr -> Bool
nullAllLedgerPeers PublicRootPeers peeraddr
prp =
  PublicRootPeers peeraddr -> Bool
forall peeraddr. PublicRootPeers peeraddr -> Bool
nullLedgerPeers PublicRootPeers peeraddr
prp Bool -> Bool -> Bool
&& PublicRootPeers peeraddr -> Bool
forall peeraddr. PublicRootPeers peeraddr -> Bool
nullBigLedgerPeers PublicRootPeers peeraddr
prp

null :: PublicRootPeers peeraddr -> Bool
null :: forall peeraddr. PublicRootPeers peeraddr -> Bool
null PublicRootPeers peeraddr
prp = PublicRootPeers peeraddr -> Bool
forall peeraddr. PublicRootPeers peeraddr -> Bool
nullPublicConfig PublicRootPeers peeraddr
prp
        Bool -> Bool -> Bool
&& PublicRootPeers peeraddr -> Bool
forall peeraddr. PublicRootPeers peeraddr -> Bool
nullBootstrap PublicRootPeers peeraddr
prp
        Bool -> Bool -> Bool
&& PublicRootPeers peeraddr -> Bool
forall peeraddr. PublicRootPeers peeraddr -> Bool
nullAllLedgerPeers PublicRootPeers peeraddr
prp

size :: PublicRootPeers peeraddr -> Int
size :: forall peeraddr. PublicRootPeers peeraddr -> Int
size (PublicRootPeers Map peeraddr PeerAdvertise
pp Set peeraddr
bsp Set peeraddr
lp Set peeraddr
blp) =
    Map peeraddr PeerAdvertise -> Int
forall k a. Map k a -> Int
Map.size Map peeraddr PeerAdvertise
pp
  Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Set peeraddr -> Int
forall a. Set a -> Int
Set.size Set peeraddr
bsp
  Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Set peeraddr -> Int
forall a. Set a -> Int
Set.size Set peeraddr
lp
  Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Set peeraddr -> Int
forall a. Set a -> Int
Set.size Set peeraddr
blp

member :: Ord peeraddr => peeraddr -> PublicRootPeers peeraddr -> Bool
member :: forall peeraddr.
Ord peeraddr =>
peeraddr -> PublicRootPeers peeraddr -> Bool
member peeraddr
p (PublicRootPeers Map peeraddr PeerAdvertise
pp Set peeraddr
bsp Set peeraddr
lp Set peeraddr
blp) =
     peeraddr -> Map peeraddr PeerAdvertise -> Bool
forall k a. Ord k => k -> Map k a -> Bool
Map.member peeraddr
p Map peeraddr PeerAdvertise
pp
  Bool -> Bool -> Bool
|| peeraddr -> Set peeraddr -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member peeraddr
p Set peeraddr
bsp
  Bool -> Bool -> Bool
|| peeraddr -> Set peeraddr -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member peeraddr
p Set peeraddr
lp
  Bool -> Bool -> Bool
|| peeraddr -> Set peeraddr -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member peeraddr
p Set peeraddr
blp

instance Ord peeraddr => Semigroup (PublicRootPeers peeraddr) where
  <> :: PublicRootPeers peeraddr
-> PublicRootPeers peeraddr -> PublicRootPeers peeraddr
(<>) = PublicRootPeers peeraddr
-> PublicRootPeers peeraddr -> PublicRootPeers peeraddr
forall peeraddr.
Ord peeraddr =>
PublicRootPeers peeraddr
-> PublicRootPeers peeraddr -> PublicRootPeers peeraddr
merge

instance Ord peeraddr => Monoid (PublicRootPeers peeraddr) where
  mempty :: PublicRootPeers peeraddr
mempty = PublicRootPeers peeraddr
forall peeraddr. PublicRootPeers peeraddr
empty

merge :: Ord peeraddr
      => PublicRootPeers peeraddr
      -> PublicRootPeers peeraddr
      -> PublicRootPeers peeraddr
merge :: forall peeraddr.
Ord peeraddr =>
PublicRootPeers peeraddr
-> PublicRootPeers peeraddr -> PublicRootPeers peeraddr
merge (PublicRootPeers Map peeraddr PeerAdvertise
pp Set peeraddr
bsp Set peeraddr
lp Set peeraddr
blp) (PublicRootPeers Map peeraddr PeerAdvertise
pp' Set peeraddr
bsp' Set peeraddr
lp' Set peeraddr
blp') =
  Map peeraddr PeerAdvertise
-> Set peeraddr
-> Set peeraddr
-> Set peeraddr
-> PublicRootPeers peeraddr
forall peeraddr.
Ord peeraddr =>
Map peeraddr PeerAdvertise
-> Set peeraddr
-> Set peeraddr
-> Set peeraddr
-> PublicRootPeers peeraddr
fromMapAndSet (Map peeraddr PeerAdvertise
pp Map peeraddr PeerAdvertise
-> Map peeraddr PeerAdvertise -> Map peeraddr PeerAdvertise
forall a. Semigroup a => a -> a -> a
<> Map peeraddr PeerAdvertise
pp') (Set peeraddr
bsp Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Semigroup a => a -> a -> a
<> Set peeraddr
bsp') (Set peeraddr
lp Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Semigroup a => a -> a -> a
<> Set peeraddr
lp') (Set peeraddr
blp Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Semigroup a => a -> a -> a
<> Set peeraddr
blp')

difference :: Ord peeraddr
           => PublicRootPeers peeraddr
           -> Set peeraddr
           -> PublicRootPeers peeraddr
difference :: forall peeraddr.
Ord peeraddr =>
PublicRootPeers peeraddr
-> Set peeraddr -> PublicRootPeers peeraddr
difference (PublicRootPeers Map peeraddr PeerAdvertise
pp Set peeraddr
bsp Set peeraddr
lp Set peeraddr
blp) Set peeraddr
addrs =
  Map peeraddr PeerAdvertise
-> Set peeraddr
-> Set peeraddr
-> Set peeraddr
-> PublicRootPeers peeraddr
forall peeraddr.
Map peeraddr PeerAdvertise
-> Set peeraddr
-> Set peeraddr
-> Set peeraddr
-> PublicRootPeers peeraddr
PublicRootPeers (Map peeraddr PeerAdvertise
pp Map peeraddr PeerAdvertise
-> Set peeraddr -> Map peeraddr PeerAdvertise
forall k a. Ord k => Map k a -> Set k -> Map k a
`Map.withoutKeys` Set peeraddr
addrs)
                  (Set peeraddr
bsp Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Ord a => Set a -> Set a -> Set a
\\ Set peeraddr
addrs)
                  (Set peeraddr
lp Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Ord a => Set a -> Set a -> Set a
\\ Set peeraddr
addrs)
                  (Set peeraddr
blp Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Ord a => Set a -> Set a -> Set a
\\ Set peeraddr
addrs)

intersection :: Ord peeraddr
             => PublicRootPeers peeraddr
             -> Set peeraddr
             -> PublicRootPeers peeraddr
intersection :: forall peeraddr.
Ord peeraddr =>
PublicRootPeers peeraddr
-> Set peeraddr -> PublicRootPeers peeraddr
intersection (PublicRootPeers Map peeraddr PeerAdvertise
pp Set peeraddr
bsp Set peeraddr
lp Set peeraddr
blp) Set peeraddr
addrs =
  Map peeraddr PeerAdvertise
-> Set peeraddr
-> Set peeraddr
-> Set peeraddr
-> PublicRootPeers peeraddr
forall peeraddr.
Map peeraddr PeerAdvertise
-> Set peeraddr
-> Set peeraddr
-> Set peeraddr
-> PublicRootPeers peeraddr
PublicRootPeers (Map peeraddr PeerAdvertise
pp Map peeraddr PeerAdvertise
-> Set peeraddr -> Map peeraddr PeerAdvertise
forall k a. Ord k => Map k a -> Set k -> Map k a
`Map.restrictKeys` Set peeraddr
addrs)
                  (Set peeraddr
bsp Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Ord a => Set a -> Set a -> Set a
`Set.intersection` Set peeraddr
addrs)
                  (Set peeraddr
lp Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Ord a => Set a -> Set a -> Set a
`Set.intersection` Set peeraddr
addrs)
                  (Set peeraddr
blp Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Ord a => Set a -> Set a -> Set a
`Set.intersection` Set peeraddr
addrs)

toSet :: Ord peeraddr => PublicRootPeers peeraddr -> Set peeraddr
toSet :: forall peeraddr.
Ord peeraddr =>
PublicRootPeers peeraddr -> Set peeraddr
toSet (PublicRootPeers Map peeraddr PeerAdvertise
pp Set peeraddr
bsp Set peeraddr
lp Set peeraddr
blp) =
  Map peeraddr PeerAdvertise -> Set peeraddr
forall k a. Map k a -> Set k
Map.keysSet Map peeraddr PeerAdvertise
pp Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Semigroup a => a -> a -> a
<> Set peeraddr
bsp Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Semigroup a => a -> a -> a
<> Set peeraddr
lp Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Semigroup a => a -> a -> a
<> Set peeraddr
blp

toPublicConfigPeerSet :: PublicRootPeers peeraddr -> Set peeraddr
toPublicConfigPeerSet :: forall peeraddr. PublicRootPeers peeraddr -> Set peeraddr
toPublicConfigPeerSet (PublicRootPeers Map peeraddr PeerAdvertise
pp Set peeraddr
_ Set peeraddr
_ Set peeraddr
_) = Map peeraddr PeerAdvertise -> Set peeraddr
forall k a. Map k a -> Set k
Map.keysSet Map peeraddr PeerAdvertise
pp

toAllLedgerPeerSet :: Ord peeraddr => PublicRootPeers peeraddr -> Set peeraddr
toAllLedgerPeerSet :: forall peeraddr.
Ord peeraddr =>
PublicRootPeers peeraddr -> Set peeraddr
toAllLedgerPeerSet (PublicRootPeers Map peeraddr PeerAdvertise
_ Set peeraddr
_ Set peeraddr
lp Set peeraddr
blp) = Set peeraddr
lp Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Semigroup a => a -> a -> a
<> Set peeraddr
blp

-- | Preserves PublicRootPeers invariant. If the two sets are not disjoint,
-- removes the common ones from the bootstrap peers set since its the most
-- sensitive set.
--
fromMapAndSet :: Ord peeraddr
              => Map peeraddr PeerAdvertise -- ^ public configured root peers
              -> Set peeraddr -- ^ bootstrap peers
              -> Set peeraddr -- ^ ledger peers
              -> Set peeraddr -- ^ big ledger peers
              -> PublicRootPeers peeraddr
fromMapAndSet :: forall peeraddr.
Ord peeraddr =>
Map peeraddr PeerAdvertise
-> Set peeraddr
-> Set peeraddr
-> Set peeraddr
-> PublicRootPeers peeraddr
fromMapAndSet Map peeraddr PeerAdvertise
pp Set peeraddr
bsp Set peeraddr
lp Set peeraddr
blp =
  -- Enforcing invariants
  let newPP :: Map peeraddr PeerAdvertise
newPP = Map peeraddr PeerAdvertise
pp Map peeraddr PeerAdvertise
-> Set peeraddr -> Map peeraddr PeerAdvertise
forall k a. Ord k => Map k a -> Set k -> Map k a
`Map.withoutKeys` (Set peeraddr
bsp Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Semigroup a => a -> a -> a
<> Set peeraddr
lp Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Semigroup a => a -> a -> a
<> Set peeraddr
blp)
      newLP :: Set peeraddr
newLP = Set peeraddr
lp Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Ord a => Set a -> Set a -> Set a
\\ (Set peeraddr
bsp Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Semigroup a => a -> a -> a
<> Set peeraddr
blp)
      newBLP :: Set peeraddr
newBLP = Set peeraddr
blp Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Ord a => Set a -> Set a -> Set a
\\ Set peeraddr
bsp
   in Map peeraddr PeerAdvertise
-> Set peeraddr
-> Set peeraddr
-> Set peeraddr
-> PublicRootPeers peeraddr
forall peeraddr.
Map peeraddr PeerAdvertise
-> Set peeraddr
-> Set peeraddr
-> Set peeraddr
-> PublicRootPeers peeraddr
PublicRootPeers Map peeraddr PeerAdvertise
newPP Set peeraddr
bsp Set peeraddr
newLP Set peeraddr
newBLP

fromPublicRootPeers :: Map peeraddr PeerAdvertise
                    -> PublicRootPeers peeraddr
fromPublicRootPeers :: forall peeraddr.
Map peeraddr PeerAdvertise -> PublicRootPeers peeraddr
fromPublicRootPeers Map peeraddr PeerAdvertise
pp =
  PublicRootPeers peeraddr
forall peeraddr. PublicRootPeers peeraddr
empty { getPublicConfigPeers = pp }

fromBootstrapPeers :: Set peeraddr
                   -> PublicRootPeers peeraddr
fromBootstrapPeers :: forall peeraddr. Set peeraddr -> PublicRootPeers peeraddr
fromBootstrapPeers Set peeraddr
bsp =
  PublicRootPeers peeraddr
forall peeraddr. PublicRootPeers peeraddr
empty { getBootstrapPeers = bsp }

fromLedgerPeers :: Set peeraddr
                -> PublicRootPeers peeraddr
fromLedgerPeers :: forall peeraddr. Set peeraddr -> PublicRootPeers peeraddr
fromLedgerPeers Set peeraddr
lp =
  PublicRootPeers peeraddr
forall peeraddr. PublicRootPeers peeraddr
empty { getLedgerPeers = lp }

fromBigLedgerPeers :: Set peeraddr
                   -> PublicRootPeers peeraddr
fromBigLedgerPeers :: forall peeraddr. Set peeraddr -> PublicRootPeers peeraddr
fromBigLedgerPeers Set peeraddr
blp =
  PublicRootPeers peeraddr
forall peeraddr. PublicRootPeers peeraddr
empty { getBigLedgerPeers = blp }

insertPublicConfigPeer :: Ord peeraddr
                       => peeraddr
                       -> PeerAdvertise
                       -> PublicRootPeers peeraddr
                       -> PublicRootPeers peeraddr
insertPublicConfigPeer :: forall peeraddr.
Ord peeraddr =>
peeraddr
-> PeerAdvertise
-> PublicRootPeers peeraddr
-> PublicRootPeers peeraddr
insertPublicConfigPeer peeraddr
p PeerAdvertise
pa prp :: PublicRootPeers peeraddr
prp@PublicRootPeers { Set peeraddr
getBootstrapPeers :: forall peeraddr. PublicRootPeers peeraddr -> Set peeraddr
getBootstrapPeers :: Set peeraddr
getBootstrapPeers } =
  let prp' :: PublicRootPeers peeraddr
prp'@PublicRootPeers{ Map peeraddr PeerAdvertise
getPublicConfigPeers :: forall peeraddr.
PublicRootPeers peeraddr -> Map peeraddr PeerAdvertise
getPublicConfigPeers :: Map peeraddr PeerAdvertise
getPublicConfigPeers } = PublicRootPeers peeraddr
-> Set peeraddr -> PublicRootPeers peeraddr
forall peeraddr.
Ord peeraddr =>
PublicRootPeers peeraddr
-> Set peeraddr -> PublicRootPeers peeraddr
difference PublicRootPeers peeraddr
prp (peeraddr -> Set peeraddr
forall a. a -> Set a
Set.singleton peeraddr
p)
   in if peeraddr -> Set peeraddr -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member peeraddr
p Set peeraddr
getBootstrapPeers
         then PublicRootPeers peeraddr
prp
         else PublicRootPeers peeraddr
prp' { getPublicConfigPeers = Map.insert p pa getPublicConfigPeers }

insertBootstrapPeer :: Ord peeraddr
                    => peeraddr
                    -> PublicRootPeers peeraddr
                    -> PublicRootPeers peeraddr
insertBootstrapPeer :: forall peeraddr.
Ord peeraddr =>
peeraddr -> PublicRootPeers peeraddr -> PublicRootPeers peeraddr
insertBootstrapPeer peeraddr
p PublicRootPeers peeraddr
prp =
  let prp' :: PublicRootPeers peeraddr
prp'@PublicRootPeers { Set peeraddr
getBootstrapPeers :: forall peeraddr. PublicRootPeers peeraddr -> Set peeraddr
getBootstrapPeers :: Set peeraddr
getBootstrapPeers } = PublicRootPeers peeraddr
-> Set peeraddr -> PublicRootPeers peeraddr
forall peeraddr.
Ord peeraddr =>
PublicRootPeers peeraddr
-> Set peeraddr -> PublicRootPeers peeraddr
difference PublicRootPeers peeraddr
prp (peeraddr -> Set peeraddr
forall a. a -> Set a
Set.singleton peeraddr
p)
   in PublicRootPeers peeraddr
prp' { getBootstrapPeers = Set.insert p getBootstrapPeers }

insertLedgerPeer :: Ord peeraddr
                 => peeraddr
                 -> PublicRootPeers peeraddr
                 -> PublicRootPeers peeraddr
insertLedgerPeer :: forall peeraddr.
Ord peeraddr =>
peeraddr -> PublicRootPeers peeraddr -> PublicRootPeers peeraddr
insertLedgerPeer peeraddr
p prp :: PublicRootPeers peeraddr
prp@PublicRootPeers{ Set peeraddr
getBootstrapPeers :: forall peeraddr. PublicRootPeers peeraddr -> Set peeraddr
getBootstrapPeers :: Set peeraddr
getBootstrapPeers } =
  let prp' :: PublicRootPeers peeraddr
prp'@PublicRootPeers { Set peeraddr
getLedgerPeers :: forall peeraddr. PublicRootPeers peeraddr -> Set peeraddr
getLedgerPeers :: Set peeraddr
getLedgerPeers } = PublicRootPeers peeraddr
-> Set peeraddr -> PublicRootPeers peeraddr
forall peeraddr.
Ord peeraddr =>
PublicRootPeers peeraddr
-> Set peeraddr -> PublicRootPeers peeraddr
difference PublicRootPeers peeraddr
prp (peeraddr -> Set peeraddr
forall a. a -> Set a
Set.singleton peeraddr
p)
   in if peeraddr -> Set peeraddr -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member peeraddr
p Set peeraddr
getBootstrapPeers
         then PublicRootPeers peeraddr
prp
         else PublicRootPeers peeraddr
prp' {getLedgerPeers = Set.insert p getLedgerPeers }

insertBigLedgerPeer :: Ord peeraddr
                    => peeraddr
                    -> PublicRootPeers peeraddr
                    -> PublicRootPeers peeraddr
insertBigLedgerPeer :: forall peeraddr.
Ord peeraddr =>
peeraddr -> PublicRootPeers peeraddr -> PublicRootPeers peeraddr
insertBigLedgerPeer peeraddr
p prp :: PublicRootPeers peeraddr
prp@PublicRootPeers { Set peeraddr
getBootstrapPeers :: forall peeraddr. PublicRootPeers peeraddr -> Set peeraddr
getBootstrapPeers :: Set peeraddr
getBootstrapPeers } =
  let prp' :: PublicRootPeers peeraddr
prp'@PublicRootPeers { Set peeraddr
getBigLedgerPeers :: forall peeraddr. PublicRootPeers peeraddr -> Set peeraddr
getBigLedgerPeers :: Set peeraddr
getBigLedgerPeers } = PublicRootPeers peeraddr
-> Set peeraddr -> PublicRootPeers peeraddr
forall peeraddr.
Ord peeraddr =>
PublicRootPeers peeraddr
-> Set peeraddr -> PublicRootPeers peeraddr
difference PublicRootPeers peeraddr
prp (peeraddr -> Set peeraddr
forall a. a -> Set a
Set.singleton peeraddr
p)
   in if peeraddr -> Set peeraddr -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member peeraddr
p Set peeraddr
getBootstrapPeers
         then PublicRootPeers peeraddr
prp
         else PublicRootPeers peeraddr
prp' { getBigLedgerPeers = Set.insert p getBigLedgerPeers }