{-# LANGUAGE NamedFieldPuns     #-}

{-# OPTIONS_GHC -Wno-orphans #-}
{-# LANGUAGE StandaloneDeriving #-}

module Test.Ouroboros.Network.PeerSelection.LocalRootPeers
  ( arbitraryLocalRootPeers
  , restrictKeys
  , tests
  , LocalRootPeers (..)
  , HotValency (..)
  , WarmValency (..)
  ) where

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.Governor
import Ouroboros.Network.PeerSelection.State.LocalRootPeers (HotValency (..),
           LocalRootConfig (..), LocalRootPeers (..), WarmValency (..))
import Ouroboros.Network.PeerSelection.State.LocalRootPeers qualified as LocalRootPeers

import Ouroboros.Network.Testing.Utils (ShrinkCarefully, prop_shrink_nonequal,
           prop_shrink_valid, renderRanges)
import Test.Ouroboros.Network.PeerSelection.Instances


import Test.QuickCheck
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.QuickCheck (testProperty)


tests :: TestTree
tests :: TestTree
tests =
  TestName -> [TestTree] -> TestTree
testGroup TestName
"Ouroboros.Network.PeerSelection"
  [ TestName -> [TestTree] -> TestTree
testGroup TestName
"LocalRootPeers"
    [ TestName -> (LocalRootPeers PeerAddr -> Property) -> TestTree
forall a. Testable a => TestName -> a -> TestTree
testProperty TestName
"arbitrary"    LocalRootPeers PeerAddr -> Property
prop_arbitrary_LocalRootPeers
    , TestName -> (LocalRootPeers PeerAddr -> Bool) -> TestTree
forall a. Testable a => TestName -> a -> TestTree
testProperty TestName
"fromToGroups" LocalRootPeers PeerAddr -> Bool
prop_fromToGroups
    , TestName
-> ([(HotValency, WarmValency, Map PeerAddr LocalRootConfig)]
    -> Bool)
-> TestTree
forall a. Testable a => TestName -> a -> TestTree
testProperty TestName
"fromGroups"   [(HotValency, WarmValency, Map PeerAddr LocalRootConfig)] -> Bool
prop_fromGroups
    , TestName
-> (ShrinkCarefully (LocalRootPeers PeerAddr) -> Property)
-> TestTree
forall a. Testable a => TestName -> a -> TestTree
testProperty TestName
"shrink"       ShrinkCarefully (LocalRootPeers PeerAddr) -> Property
prop_shrink_LocalRootPeers
    , TestName
-> (LocalRootPeers PeerAddr -> PeerSelectionTargets -> Property)
-> TestTree
forall a. Testable a => TestName -> a -> TestTree
testProperty TestName
"clampToLimit" LocalRootPeers PeerAddr -> PeerSelectionTargets -> Property
prop_clampToLimit
    , TestName -> (LocalRootPeers PeerAddr -> Property) -> TestTree
forall a. Testable a => TestName -> a -> TestTree
testProperty TestName
"clampToTrustable" LocalRootPeers PeerAddr -> Property
prop_clampToTrustable
    ]
  ]


-- | Check that we can forcibly bring the localRootPeers into compliance
-- with the governor's state invariant, which requires that the local
-- root peers fit within the current targets.
--
-- The precondition on the targets is that they are sane.
-- See sanePeerSelectionTargets.
prop_clampToLimit :: LocalRootPeers PeerAddr -> PeerSelectionTargets -> Property
prop_clampToLimit :: LocalRootPeers PeerAddr -> PeerSelectionTargets -> Property
prop_clampToLimit LocalRootPeers PeerAddr
localRootPeers PeerSelectionTargets
targets =

    let sizeLimit :: Int
sizeLimit       = PeerSelectionTargets -> Int
targetNumberOfKnownPeers PeerSelectionTargets
targets
        localRootPeers' :: LocalRootPeers PeerAddr
localRootPeers' = Int -> LocalRootPeers PeerAddr -> LocalRootPeers PeerAddr
forall peeraddr.
Ord peeraddr =>
Int -> LocalRootPeers peeraddr -> LocalRootPeers peeraddr
LocalRootPeers.clampToLimit Int
sizeLimit LocalRootPeers PeerAddr
localRootPeers

     in TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
counterexample (TestName
"sizeLimit   = " TestName -> TestName -> TestName
forall a. [a] -> [a] -> [a]
++ Int -> TestName
forall a. Show a => a -> TestName
show Int
sizeLimit) (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$

        LocalRootPeers PeerAddr -> Int
forall peeraddr. LocalRootPeers peeraddr -> Int
LocalRootPeers.size LocalRootPeers PeerAddr
localRootPeers'
          Int -> Int -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
sizeLimit
                 (LocalRootPeers PeerAddr -> Int
forall peeraddr. LocalRootPeers peeraddr -> Int
LocalRootPeers.size LocalRootPeers PeerAddr
localRootPeers)

prop_clampToTrustable :: LocalRootPeers PeerAddr -> Property
prop_clampToTrustable :: LocalRootPeers PeerAddr -> Property
prop_clampToTrustable LocalRootPeers PeerAddr
localRootPeers =

    let trustedPeers :: Set PeerAddr
trustedPeers = LocalRootPeers PeerAddr -> Set PeerAddr
forall peeraddr. LocalRootPeers peeraddr -> Set peeraddr
LocalRootPeers.keysSet
                     (LocalRootPeers PeerAddr -> Set PeerAddr)
-> LocalRootPeers PeerAddr -> Set PeerAddr
forall a b. (a -> b) -> a -> b
$ LocalRootPeers PeerAddr -> LocalRootPeers PeerAddr
forall peeraddr.
Ord peeraddr =>
LocalRootPeers peeraddr -> LocalRootPeers peeraddr
LocalRootPeers.clampToTrustable LocalRootPeers PeerAddr
localRootPeers

     in TestName -> Bool -> Property
forall prop. Testable prop => TestName -> prop -> Property
counterexample (Map PeerAddr LocalRootConfig -> TestName
forall a. Show a => a -> TestName
show (Map PeerAddr LocalRootConfig -> TestName)
-> Map PeerAddr LocalRootConfig -> TestName
forall a b. (a -> b) -> a -> b
$ Map PeerAddr LocalRootConfig
-> Set PeerAddr -> Map PeerAddr LocalRootConfig
forall k a. Ord k => Map k a -> Set k -> Map k a
Map.restrictKeys (LocalRootPeers PeerAddr -> Map PeerAddr LocalRootConfig
forall peeraddr.
LocalRootPeers peeraddr -> Map peeraddr LocalRootConfig
LocalRootPeers.toMap LocalRootPeers PeerAddr
localRootPeers) Set PeerAddr
trustedPeers)
      (Bool -> Property) -> Bool -> Property
forall a b. (a -> b) -> a -> b
$ (PeerAddr -> Bool) -> Set PeerAddr -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (PeerAddr -> LocalRootPeers PeerAddr -> Bool
forall peeraddr.
Ord peeraddr =>
peeraddr -> LocalRootPeers peeraddr -> Bool
`LocalRootPeers.isPeerTrustable` LocalRootPeers PeerAddr
localRootPeers) Set PeerAddr
trustedPeers


arbitraryLocalRootPeers :: Ord peeraddr
                        => Set peeraddr -> Gen (LocalRootPeers peeraddr)
arbitraryLocalRootPeers :: forall peeraddr.
Ord peeraddr =>
Set peeraddr -> Gen (LocalRootPeers peeraddr)
arbitraryLocalRootPeers Set peeraddr
peeraddrs = do
    -- divide into a few disjoint groups
    ngroups     <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5 :: Int)
    gassignment <- vectorOf (Set.size peeraddrs) (choose (1, ngroups))
    advertise   <- vectorOf (Set.size peeraddrs) arbitrary
    let groups = Map Int (Map peeraddr LocalRootConfig)
-> [Map peeraddr LocalRootConfig]
forall k a. Map k a -> [a]
Map.elems (Map Int (Map peeraddr LocalRootConfig)
 -> [Map peeraddr LocalRootConfig])
-> Map Int (Map peeraddr LocalRootConfig)
-> [Map peeraddr LocalRootConfig]
forall a b. (a -> b) -> a -> b
$
                 (Map peeraddr LocalRootConfig
 -> Map peeraddr LocalRootConfig -> Map peeraddr LocalRootConfig)
-> [(Int, Map peeraddr LocalRootConfig)]
-> Map Int (Map peeraddr LocalRootConfig)
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith Map peeraddr LocalRootConfig
-> Map peeraddr LocalRootConfig -> Map peeraddr LocalRootConfig
forall k a. Ord k => Map k a -> Map k a -> Map k a
Map.union
                   [ (Int
gn, peeraddr -> LocalRootConfig -> Map peeraddr LocalRootConfig
forall k a. k -> a -> Map k a
Map.singleton peeraddr
p LocalRootConfig
a)
                   | (peeraddr
p, Int
gn, LocalRootConfig
a) <- [peeraddr]
-> [Int] -> [LocalRootConfig] -> [(peeraddr, Int, LocalRootConfig)]
forall a b c. [a] -> [b] -> [c] -> [(a, b, c)]
zip3 (Set peeraddr -> [peeraddr]
forall a. Set a -> [a]
Set.toList Set peeraddr
peeraddrs)
                                         [Int]
gassignment
                                         [LocalRootConfig]
advertise
                   ]
    targets <- mapM (\Map peeraddr LocalRootConfig
g -> do
                      warmValency <- Int -> WarmValency
WarmValency (Int -> WarmValency) -> Gen Int -> Gen WarmValency
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
0, Map peeraddr LocalRootConfig -> Int
forall k a. Map k a -> Int
Map.size Map peeraddr LocalRootConfig
g)
                      hotValency <- HotValency <$> choose (0, getWarmValency warmValency)
                      return (hotValency, warmValency)
                    ) groups

    return (LocalRootPeers.fromGroups (zipWith (\(HotValency
h, WarmValency
w) Map peeraddr LocalRootConfig
g -> (HotValency
h, WarmValency
w, Map peeraddr LocalRootConfig
g))
                                               targets
                                               groups))

instance Arbitrary HotValency where
  arbitrary :: Gen HotValency
arbitrary = Int -> HotValency
HotValency (Int -> HotValency) -> Gen Int -> Gen HotValency
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Int
forall a. Arbitrary a => Gen a
arbitrary

instance Arbitrary WarmValency where
  arbitrary :: Gen WarmValency
arbitrary = Int -> WarmValency
WarmValency (Int -> WarmValency) -> Gen Int -> Gen WarmValency
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Int
forall a. Arbitrary a => Gen a
arbitrary

instance (Arbitrary peeraddr, Ord peeraddr) =>
         Arbitrary (LocalRootPeers peeraddr) where
    arbitrary :: Gen (LocalRootPeers peeraddr)
arbitrary = do
        peeraddrs <- (Int -> Int) -> Gen (Set peeraddr) -> Gen (Set peeraddr)
forall a. (Int -> Int) -> Gen a -> Gen a
scale (Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
4) Gen (Set peeraddr)
forall a. Arbitrary a => Gen a
arbitrary
        arbitraryLocalRootPeers peeraddrs

    shrink :: LocalRootPeers peeraddr -> [LocalRootPeers peeraddr]
shrink LocalRootPeers peeraddr
lrps =
        ([(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
 -> LocalRootPeers peeraddr)
-> [[(HotValency, WarmValency, Map peeraddr LocalRootConfig)]]
-> [LocalRootPeers peeraddr]
forall a b. (a -> b) -> [a] -> [b]
map [(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
-> LocalRootPeers peeraddr
forall peeraddr.
Ord peeraddr =>
[(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
-> LocalRootPeers peeraddr
LocalRootPeers.fromGroups ([(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
-> [[(HotValency, WarmValency, Map peeraddr LocalRootConfig)]]
forall a. Arbitrary a => a -> [a]
shrink (LocalRootPeers peeraddr
-> [(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
forall peeraddr.
Ord peeraddr =>
LocalRootPeers peeraddr
-> [(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
LocalRootPeers.toGroups LocalRootPeers peeraddr
lrps))

restrictKeys :: Ord peeraddr
             => LocalRootPeers peeraddr
             -> Set peeraddr
             -> LocalRootPeers peeraddr
restrictKeys :: forall peeraddr.
Ord peeraddr =>
LocalRootPeers peeraddr -> Set peeraddr -> LocalRootPeers peeraddr
restrictKeys LocalRootPeers peeraddr
lrps Set peeraddr
ks =
    [(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
-> LocalRootPeers peeraddr
forall peeraddr.
Ord peeraddr =>
[(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
-> LocalRootPeers peeraddr
LocalRootPeers.fromGroups
  ([(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
 -> LocalRootPeers peeraddr)
-> (LocalRootPeers peeraddr
    -> [(HotValency, WarmValency, Map peeraddr LocalRootConfig)])
-> LocalRootPeers peeraddr
-> LocalRootPeers peeraddr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((HotValency, WarmValency, Map peeraddr LocalRootConfig)
 -> (HotValency, WarmValency, Map peeraddr LocalRootConfig))
-> [(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
-> [(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
forall a b. (a -> b) -> [a] -> [b]
map (\(HotValency
h, WarmValency
w, Map peeraddr LocalRootConfig
g) -> (HotValency
h, WarmValency
w, Map peeraddr LocalRootConfig
-> Set peeraddr -> Map peeraddr LocalRootConfig
forall k a. Ord k => Map k a -> Set k -> Map k a
Map.restrictKeys Map peeraddr LocalRootConfig
g Set peeraddr
ks))
  ([(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
 -> [(HotValency, WarmValency, Map peeraddr LocalRootConfig)])
-> (LocalRootPeers peeraddr
    -> [(HotValency, WarmValency, Map peeraddr LocalRootConfig)])
-> LocalRootPeers peeraddr
-> [(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LocalRootPeers peeraddr
-> [(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
forall peeraddr.
Ord peeraddr =>
LocalRootPeers peeraddr
-> [(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
LocalRootPeers.toGroups
  (LocalRootPeers peeraddr -> LocalRootPeers peeraddr)
-> LocalRootPeers peeraddr -> LocalRootPeers peeraddr
forall a b. (a -> b) -> a -> b
$ LocalRootPeers peeraddr
lrps

prop_arbitrary_LocalRootPeers :: LocalRootPeers PeerAddr -> Property
prop_arbitrary_LocalRootPeers :: LocalRootPeers PeerAddr -> Property
prop_arbitrary_LocalRootPeers LocalRootPeers PeerAddr
lrps =
    TestName -> [TestName] -> Property -> Property
forall prop.
Testable prop =>
TestName -> [TestName] -> prop -> Property
tabulate TestName
"total size"    [TestName
size] (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
    TestName -> [TestName] -> Property -> Property
forall prop.
Testable prop =>
TestName -> [TestName] -> prop -> Property
tabulate TestName
"num groups"    [TestName
numGroups] (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
    TestName -> [TestName] -> Property -> Property
forall prop.
Testable prop =>
TestName -> [TestName] -> prop -> Property
tabulate TestName
"group size"    [TestName]
sizeGroups (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
    TestName -> [TestName] -> Bool -> Property
forall prop.
Testable prop =>
TestName -> [TestName] -> prop -> Property
tabulate TestName
"targets"       [TestName]
targets (Bool -> Property) -> Bool -> Property
forall a b. (a -> b) -> a -> b
$

    LocalRootPeers PeerAddr -> Bool
forall peeraddr. Ord peeraddr => LocalRootPeers peeraddr -> Bool
LocalRootPeers.invariant LocalRootPeers PeerAddr
lrps
  where
    thrd :: (a, b, c) -> c
thrd (a
_, b
_, c
c) = c
c
    size :: TestName
size       = Int -> Int -> TestName
renderRanges Int
5 (LocalRootPeers PeerAddr -> Int
forall peeraddr. LocalRootPeers peeraddr -> Int
LocalRootPeers.size LocalRootPeers PeerAddr
lrps)
    numGroups :: TestName
numGroups  = Int -> TestName
forall a. Show a => a -> TestName
show ([(HotValency, WarmValency, Map PeerAddr LocalRootConfig)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (LocalRootPeers PeerAddr
-> [(HotValency, WarmValency, Map PeerAddr LocalRootConfig)]
forall peeraddr.
Ord peeraddr =>
LocalRootPeers peeraddr
-> [(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
LocalRootPeers.toGroups LocalRootPeers PeerAddr
lrps))
    sizeGroups :: [TestName]
sizeGroups = ((HotValency, WarmValency, Set PeerAddr) -> TestName)
-> [(HotValency, WarmValency, Set PeerAddr)] -> [TestName]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> TestName
forall a. Show a => a -> TestName
show (Int -> TestName)
-> ((HotValency, WarmValency, Set PeerAddr) -> Int)
-> (HotValency, WarmValency, Set PeerAddr)
-> TestName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Set PeerAddr -> Int
forall a. Set a -> Int
Set.size (Set PeerAddr -> Int)
-> ((HotValency, WarmValency, Set PeerAddr) -> Set PeerAddr)
-> (HotValency, WarmValency, Set PeerAddr)
-> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (HotValency, WarmValency, Set PeerAddr) -> Set PeerAddr
forall {a} {b} {c}. (a, b, c) -> c
thrd) (LocalRootPeers PeerAddr
-> [(HotValency, WarmValency, Set PeerAddr)]
forall peeraddr.
LocalRootPeers peeraddr
-> [(HotValency, WarmValency, Set peeraddr)]
LocalRootPeers.toGroupSets LocalRootPeers PeerAddr
lrps)
    targets :: [TestName]
targets    = [ case () of
                    ()
_ | HotValency
h HotValency -> HotValency -> Bool
forall a. Eq a => a -> a -> Bool
== HotValency
0                        -> TestName
"none active"
                      | WarmValency
w WarmValency -> WarmValency -> Bool
forall a. Eq a => a -> a -> Bool
== WarmValency
0                        -> TestName
"none established"
                      | HotValency
h HotValency -> HotValency -> Bool
forall a. Eq a => a -> a -> Bool
== Int -> HotValency
HotValency (Set PeerAddr -> Int
forall a. Set a -> Int
Set.size Set PeerAddr
g)  -> TestName
"all active"
                      | WarmValency
w WarmValency -> WarmValency -> Bool
forall a. Eq a => a -> a -> Bool
== Int -> WarmValency
WarmValency (Set PeerAddr -> Int
forall a. Set a -> Int
Set.size Set PeerAddr
g) -> TestName
"all established"
                      | Bool
otherwise                     -> TestName
"some"
                 | (HotValency
h, WarmValency
w, Set PeerAddr
g) <- LocalRootPeers PeerAddr
-> [(HotValency, WarmValency, Set PeerAddr)]
forall peeraddr.
LocalRootPeers peeraddr
-> [(HotValency, WarmValency, Set peeraddr)]
LocalRootPeers.toGroupSets LocalRootPeers PeerAddr
lrps ]


prop_shrink_LocalRootPeers :: ShrinkCarefully (LocalRootPeers PeerAddr) -> Property
prop_shrink_LocalRootPeers :: ShrinkCarefully (LocalRootPeers PeerAddr) -> Property
prop_shrink_LocalRootPeers ShrinkCarefully (LocalRootPeers PeerAddr)
x =
      (LocalRootPeers PeerAddr -> Bool)
-> ShrinkCarefully (LocalRootPeers PeerAddr) -> Property
forall a prop.
(Arbitrary a, Show a, Testable prop) =>
(a -> prop) -> ShrinkCarefully a -> Property
prop_shrink_valid LocalRootPeers PeerAddr -> Bool
forall peeraddr. Ord peeraddr => LocalRootPeers peeraddr -> Bool
LocalRootPeers.invariant ShrinkCarefully (LocalRootPeers PeerAddr)
x
 Property -> Property -> Property
forall prop1 prop2.
(Testable prop1, Testable prop2) =>
prop1 -> prop2 -> Property
.&&. ShrinkCarefully (LocalRootPeers PeerAddr) -> Property
forall a.
(Arbitrary a, Eq a, Show a) =>
ShrinkCarefully a -> Property
prop_shrink_nonequal ShrinkCarefully (LocalRootPeers PeerAddr)
x

prop_fromGroups :: [(HotValency, WarmValency, Map PeerAddr LocalRootConfig)] -> Bool
prop_fromGroups :: [(HotValency, WarmValency, Map PeerAddr LocalRootConfig)] -> Bool
prop_fromGroups = LocalRootPeers PeerAddr -> Bool
forall peeraddr. Ord peeraddr => LocalRootPeers peeraddr -> Bool
LocalRootPeers.invariant (LocalRootPeers PeerAddr -> Bool)
-> ([(HotValency, WarmValency, Map PeerAddr LocalRootConfig)]
    -> LocalRootPeers PeerAddr)
-> [(HotValency, WarmValency, Map PeerAddr LocalRootConfig)]
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(HotValency, WarmValency, Map PeerAddr LocalRootConfig)]
-> LocalRootPeers PeerAddr
forall peeraddr.
Ord peeraddr =>
[(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
-> LocalRootPeers peeraddr
LocalRootPeers.fromGroups

prop_fromToGroups :: LocalRootPeers PeerAddr -> Bool
prop_fromToGroups :: LocalRootPeers PeerAddr -> Bool
prop_fromToGroups LocalRootPeers PeerAddr
lrps =
    [(HotValency, WarmValency, Map PeerAddr LocalRootConfig)]
-> LocalRootPeers PeerAddr
forall peeraddr.
Ord peeraddr =>
[(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
-> LocalRootPeers peeraddr
LocalRootPeers.fromGroups (LocalRootPeers PeerAddr
-> [(HotValency, WarmValency, Map PeerAddr LocalRootConfig)]
forall peeraddr.
Ord peeraddr =>
LocalRootPeers peeraddr
-> [(HotValency, WarmValency, Map peeraddr LocalRootConfig)]
LocalRootPeers.toGroups LocalRootPeers PeerAddr
lrps) LocalRootPeers PeerAddr -> LocalRootPeers PeerAddr -> Bool
forall a. Eq a => a -> a -> Bool
== LocalRootPeers PeerAddr
lrps