diff --git a/ouroboros-network-framework/src/Ouroboros/Network/ConnectionManager/Core.hs b/ouroboros-network-framework/src/Ouroboros/Network/ConnectionManager/Core.hs index bfb54fab6ed..218422fec2b 100644 --- a/ouroboros-network-framework/src/Ouroboros/Network/ConnectionManager/Core.hs +++ b/ouroboros-network-framework/src/Ouroboros/Network/ConnectionManager/Core.hs @@ -2346,7 +2346,7 @@ withConnectionManager ConnectionManagerArguments { (result, mbAssertion) <- atomically $ do mbConnVar <- Map.lookup peerAddr <$> readTMVar stateVar case mbConnVar of - Nothing -> return (UnsupportedState UnknownConnectionSt + Nothing -> return ( UnsupportedState UnknownConnectionSt , Nothing ) Just MutableConnState { connVar } -> do diff --git a/ouroboros-network-framework/src/Ouroboros/Network/ConnectionManager/Types.hs b/ouroboros-network-framework/src/Ouroboros/Network/ConnectionManager/Types.hs index 7fef64ce527..157a297a894 100644 --- a/ouroboros-network-framework/src/Ouroboros/Network/ConnectionManager/Types.hs +++ b/ouroboros-network-framework/src/Ouroboros/Network/ConnectionManager/Types.hs @@ -612,7 +612,7 @@ includeInboundConnection includeInboundConnection = icmIncludeConnection . withResponderMode . getConnectionManager --- | Unregister outbound connection. Returns if the operation was successul. +-- | Unregister outbound connection. Returns if the operation was successful. -- -- This executes: -- @@ -642,8 +642,10 @@ numberOfConnections = -- | Useful for tracing and error messages. -- -data AbstractState - = UnknownConnectionSt +data AbstractState = + -- | Unknown connection. This state indicates the connection manager + -- removed this connection from its state. + UnknownConnectionSt | ReservedOutboundSt | UnnegotiatedSt !Provenance | InboundIdleSt !DataFlow @@ -839,8 +841,8 @@ data ConnectionManagerTrace peerAddr handlerTrace | TrConnectionFailure (ConnectionId peerAddr) | TrConnectionNotFound Provenance peerAddr | TrForbiddenOperation peerAddr AbstractState - | TrPruneConnections (Set peerAddr) -- ^ prunning set - Int -- ^ number connections that must be prunned + | TrPruneConnections (Set peerAddr) -- ^ pruning set + Int -- ^ number connections that must be pruned (Set peerAddr) -- ^ choice set | TrConnectionCleanup (ConnectionId peerAddr) | TrConnectionTimeWait (ConnectionId peerAddr) diff --git a/ouroboros-network-framework/src/Simulation/Network/Snocket.hs b/ouroboros-network-framework/src/Simulation/Network/Snocket.hs index f9f03065a64..e7903727067 100644 --- a/ouroboros-network-framework/src/Simulation/Network/Snocket.hs +++ b/ouroboros-network-framework/src/Simulation/Network/Snocket.hs @@ -37,6 +37,7 @@ module Simulation.Network.Snocket , FD , GlobalAddressScheme (..) , AddressType (..) + , WithAddr (..) ) where import Prelude hiding (read) @@ -134,33 +135,36 @@ mkConnection :: ( MonadLabelledSTM m -> BearerInfo -> ConnectionId (TestAddress addr) -> STM m (Connection m (TestAddress addr)) -mkConnection tr bearerInfo connId@ConnectionId { localAddress, remoteAddress } = do - (channelLocal, channelRemote) <- - newConnectedAttenuatedChannelPair - ( ( WithAddr (Just localAddress) (Just remoteAddress) - . STAttenuatedChannelTrace connId - ) - `contramap` tr) - ( ( WithAddr (Just remoteAddress) (Just localAddress) - . STAttenuatedChannelTrace ConnectionId - { localAddress = remoteAddress - , remoteAddress = localAddress - } - ) - `contramap` tr) - Attenuation - { aReadAttenuation = biOutboundAttenuation bearerInfo - , aWriteAttenuation = biOutboundWriteFailure bearerInfo - } - Attenuation - { aReadAttenuation = biInboundAttenuation bearerInfo - , aWriteAttenuation = biInboundWriteFailure bearerInfo - } - return $ Connection channelLocal - channelRemote - (biSDUSize bearerInfo) - SYN_SENT - localAddress +mkConnection tr bearerInfo connId@ConnectionId { localAddress, remoteAddress } = + (\(connChannelLocal, connChannelRemote) -> + Connection { + connChannelLocal, + connChannelRemote, + connSDUSize = biSDUSize bearerInfo, + connState = SYN_SENT, + connProvider = localAddress + }) + <$> + newConnectedAttenuatedChannelPair + ( ( WithAddr (Just localAddress) (Just remoteAddress) + . STAttenuatedChannelTrace connId + ) + `contramap` tr) + ( ( WithAddr (Just remoteAddress) (Just localAddress) + . STAttenuatedChannelTrace ConnectionId + { localAddress = remoteAddress + , remoteAddress = localAddress + } + ) + `contramap` tr) + Attenuation + { aReadAttenuation = biOutboundAttenuation bearerInfo + , aWriteAttenuation = biOutboundWriteFailure bearerInfo + } + Attenuation + { aReadAttenuation = biInboundAttenuation bearerInfo + , aWriteAttenuation = biInboundWriteFailure bearerInfo + } -- | Connection id independent of who provisioned the connection. 'NormalisedId' @@ -528,6 +532,7 @@ newtype FD m peerAddr = FD { fdVar :: (StrictTVar m (FD_ m peerAddr)) } -- Simulated snockets -- +-- TODO: use `Ouroboros.Network.ExitPolicy.WithAddr` data WithAddr addr event = WithAddr { waLocalAddr :: Maybe addr , waRemoteAddr :: Maybe addr @@ -733,9 +738,7 @@ mkSnocket state tr = Snocket { getLocalAddr normalisedId = normaliseId connId bearerInfo <- case Map.lookup normalisedId (nsAttenuationMap state) of - Nothing -> do - return (nsDefaultBearerInfo state) - + Nothing -> return (nsDefaultBearerInfo state) Just script -> stepScriptSTM script connMap <- readTVar (nsConnections state) @@ -743,6 +746,10 @@ mkSnocket state tr = Snocket { getLocalAddr Just Connection { connState = ESTABLISHED } -> throwSTM (connectedIOError fd_) + Just Connection { connState = SYN_SENT, connProvider } + | connProvider == localAddress -> + throwSTM (connectedIOError fd_) + -- simultaneous open Just conn@Connection { connState = SYN_SENT } -> do let conn' = conn { connState = ESTABLISHED } diff --git a/ouroboros-network-testing/src/Ouroboros/Network/Testing/Data/Signal.hs b/ouroboros-network-testing/src/Ouroboros/Network/Testing/Data/Signal.hs index 0d6d0061b56..f23589eb985 100644 --- a/ouroboros-network-testing/src/Ouroboros/Network/Testing/Data/Signal.hs +++ b/ouroboros-network-testing/src/Ouroboros/Network/Testing/Data/Signal.hs @@ -19,6 +19,7 @@ module Ouroboros.Network.Testing.Data.Signal , fromChangeEvents , toChangeEvents , fromEvents + , fromEventsWith -- ** QuickCheck , signalProperty -- * Simple signal transformations @@ -191,6 +192,17 @@ fromEvents (Events txs) = ] +-- | Like 'fromEvents' but it is using the given value 'a' instead of 'Nothing. +-- It is equivalent to `\a -> fmap (fromMaybe a) . fromEvents` +-- +fromEventsWith :: a -> Events a -> Signal a +fromEventsWith a (Events txs) = + Signal a + [ E (TS t i') s + | E (TS t i) x <- txs + , (i', s) <- [(i, x), (i+1, a)] + ] + -- | A signal can change value more than once at a single point of time. -- -- Sometimes we are interested only in the final \"stable\" value of the signal @@ -360,7 +372,10 @@ keyedTimeout d arm = -> Set b -> [E a] -> [E (Set b)] - go _ _ _ [] = [] + go _ armedPSQ _ [] = + (\(b, t, _) -> E (TS t 0) (Set.singleton b)) + `map` + PSQ.toList armedPSQ go armedSet armedPSQ timedout (E ts@(TS t _) x : txs) | Just (y, t', _, armedPSQ') <- PSQ.minView armedPSQ diff --git a/ouroboros-network/src/Ouroboros/Network/PeerSelection/PeerStateActions.hs b/ouroboros-network/src/Ouroboros/Network/PeerSelection/PeerStateActions.hs index 7e19ed173bb..c8eab608e90 100644 --- a/ouroboros-network/src/Ouroboros/Network/PeerSelection/PeerStateActions.hs +++ b/ouroboros-network/src/Ouroboros/Network/PeerSelection/PeerStateActions.hs @@ -24,6 +24,8 @@ module Ouroboros.Network.PeerSelection.PeerStateActions , MonitorPeerConnectionBlocked (..) -- * Trace , PeerSelectionActionsTrace (..) + , PeerStatusChangeType (..) + , FailureType (..) ) where import Control.Concurrent.Class.MonadSTM.Strict diff --git a/ouroboros-network/test/Test/Ouroboros/Network/Diffusion/Node.hs b/ouroboros-network/test/Test/Ouroboros/Network/Diffusion/Node.hs index 3ec43e1913f..a2e4cd29e9f 100644 --- a/ouroboros-network/test/Test/Ouroboros/Network/Diffusion/Node.hs +++ b/ouroboros-network/test/Test/Ouroboros/Network/Diffusion/Node.hs @@ -34,13 +34,14 @@ import Control.Monad ((>=>)) import Control.Monad.Class.MonadAsync (MonadAsync (Async, wait, withAsync)) import Control.Monad.Class.MonadFork (MonadFork) +import Control.Monad.Class.MonadSay import Control.Monad.Class.MonadST (MonadST) import Control.Monad.Class.MonadThrow (MonadEvaluate, MonadMask, MonadThrow, SomeException) import Control.Monad.Class.MonadTime (DiffTime, MonadTime) import Control.Monad.Class.MonadTimer (MonadTimer) import Control.Monad.Fix (MonadFix) -import Control.Tracer (nullTracer) +import Control.Tracer (Tracer (..), nullTracer) import Data.Foldable (foldl') import Data.IP (IP (..)) @@ -136,6 +137,7 @@ data Arguments m = Arguments , aTimeWaitTimeout :: DiffTime , aDNSTimeoutScript :: Script DNSTimeout , aDNSLookupDelayScript :: Script DNSLookupDelay + , aDebugTracer :: Tracer m String } -- The 'mockDNSActions' is not using \/ specifying 'resolverException', thus we @@ -151,6 +153,7 @@ run :: forall resolver m. , MonadLabelledSTM m , MonadTraceSTM m , MonadMask m + , MonadSay m , MonadST m , MonadTime m , MonadTimer m @@ -161,7 +164,8 @@ run :: forall resolver m. , forall a. Semigroup a => Semigroup (m a) , Eq (Async m Void) ) - => Node.BlockGeneratorArgs Block StdGen + => Tracer m String + -> Node.BlockGeneratorArgs Block StdGen -> Node.LimitsAndTimeouts Block -> Interfaces m -> Arguments m @@ -169,7 +173,7 @@ run :: forall resolver m. NtCAddr NtCVersion NtCVersionData ResolverException m -> m Void -run blockGeneratorArgs limits ni na tracersExtra = +run _debugTracer blockGeneratorArgs limits ni na tracersExtra = Node.withNodeKernelThread blockGeneratorArgs $ \ nodeKernel nodeKernelThread -> do dnsTimeoutScriptVar <- LazySTM.newTVarIO (aDNSTimeoutScript na) @@ -236,13 +240,14 @@ run blockGeneratorArgs limits ni na tracersExtra = , Diff.P2P.daReturnPolicy = \_ -> 0 } - apps <- Node.applications @_ @BlockHeader nodeKernel Node.cborCodecs limits appArgs + apps <- Node.applications @_ @BlockHeader (aDebugTracer na) nodeKernel Node.cborCodecs limits appArgs registry <- newFetchClientRegistry withAsync (Diff.P2P.runM interfaces - Diff.nullTracers tracersExtra + Diff.nullTracers + tracersExtra args argsExtra apps appsExtra) $ \ diffusionThread -> withAsync (blockFetch registry nodeKernel) $ \blockFetchLogicThread -> diff --git a/ouroboros-network/test/Test/Ouroboros/Network/Diffusion/Node/MiniProtocols.hs b/ouroboros-network/test/Test/Ouroboros/Network/Diffusion/Node/MiniProtocols.hs index c1a17f28632..bbc7373bb13 100644 --- a/ouroboros-network/test/Test/Ouroboros/Network/Diffusion/Node/MiniProtocols.hs +++ b/ouroboros-network/test/Test/Ouroboros/Network/Diffusion/Node/MiniProtocols.hs @@ -3,6 +3,7 @@ {-# LANGUAGE GADTs #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TupleSections #-} -- orphaned 'ShowProxy PingPong' instance. {-# OPTIONS_GHC -Wno-orphans #-} @@ -19,11 +20,12 @@ import qualified Control.Concurrent.Class.MonadSTM as LazySTM import Control.Concurrent.Class.MonadSTM.Strict import Control.Monad.Class.MonadAsync import Control.Monad.Class.MonadFork +import Control.Monad.Class.MonadSay import Control.Monad.Class.MonadST import Control.Monad.Class.MonadThrow import Control.Monad.Class.MonadTime import Control.Monad.Class.MonadTimer -import Control.Tracer (nullTracer) +import Control.Tracer (Tracer (..), contramap, nullTracer) import Data.ByteString.Lazy (ByteString) import Data.Functor (($>)) import Data.Maybe (fromMaybe) @@ -177,6 +179,7 @@ applications :: forall block header m. ( MonadAsync m , MonadFork m , MonadMask m + , MonadSay m , MonadThrow m , MonadTime m , MonadTimer m @@ -184,16 +187,18 @@ applications :: forall block header m. , HasHeader header , HasHeader block , HeaderHash header ~ HeaderHash block + , Show block , ShowProxy block ) - => NodeKernel header block m + => Tracer m String + -> NodeKernel header block m -> Codecs block m -> LimitsAndTimeouts block -> AppArgs m -> m (Diff.Applications NtNAddr NtNVersion NtNVersionData NtCAddr NtCVersion NtCVersionData m ()) -applications nodeKernel +applications debugTracer nodeKernel Codecs { chainSyncCodec, blockFetchCodec , keepAliveCodec, pingPongCodec } limits @@ -261,14 +266,14 @@ applications nodeKernel blockFetchResponder } ] - , withWarm = WithWarm $ \ _connId controlMessageSTM -> + , withWarm = WithWarm $ \ connId controlMessageSTM -> [ MiniProtocol { miniProtocolNum = MiniProtocolNum 9 , miniProtocolLimits = pingPongLimits limits , miniProtocolRun = InitiatorAndResponderProtocol - (pingPongInitiator controlMessageSTM) - pingPongResponder + (pingPongInitiator connId controlMessageSTM) + (pingPongResponder connId) } ] , withEstablished = WithEstablished $ \ connId controlMessageSTM -> @@ -376,13 +381,13 @@ applications nodeKernel :: ConnectionId NtNAddr -> ControlMessageSTM m -> MuxPeer ByteString m () - keepAliveInitiator ConnectionId { remoteAddress } + keepAliveInitiator connId@ConnectionId { remoteAddress } controlMessageSTM = MuxPeerRaw $ \channel -> do labelThisThread "KeepAliveClient" let kacApp = \ctxVar -> runPeerWithLimits - nullTracer + ((show . (connId,)) `contramap` debugTracer) keepAliveCodec (keepAliveSizeLimits limits) (keepAliveTimeLimits limits) @@ -412,11 +417,12 @@ applications nodeKernel (keepAliveServerPeer keepAliveServer) pingPongInitiator - :: ControlMessageSTM m + :: ConnectionId NtNAddr + -> ControlMessageSTM m -> MuxPeer ByteString m () - pingPongInitiator controlMessageSTM = MuxPeerRaw $ \channel -> + pingPongInitiator connId controlMessageSTM = MuxPeerRaw $ \channel -> runPeerWithLimits - nullTracer + ((show . (connId,)) `contramap` debugTracer) pingPongCodec (pingPongSizeLimits limits) (pingPongTimeLimits limits) @@ -451,10 +457,11 @@ applications nodeKernel else return $ PingPong.SendMsgDone () pingPongResponder - :: MuxPeer ByteString m () - pingPongResponder = MuxPeerRaw $ \channel -> + :: ConnectionId NtNAddr + -> MuxPeer ByteString m () + pingPongResponder connId = MuxPeerRaw $ \channel -> runPeerWithLimits - nullTracer + ((show . (connId,)) `contramap` debugTracer) pingPongCodec (pingPongSizeLimits limits) (pingPongTimeLimits limits) diff --git a/ouroboros-network/test/Test/Ouroboros/Network/Testnet.hs b/ouroboros-network/test/Test/Ouroboros/Network/Testnet.hs index 2b8f5e95d4a..aadee5881de 100644 --- a/ouroboros-network/test/Test/Ouroboros/Network/Testnet.hs +++ b/ouroboros-network/test/Test/Ouroboros/Network/Testnet.hs @@ -18,7 +18,6 @@ import Control.Monad.IOSim.Types (ThreadId) import Control.Tracer (Tracer (Tracer), contramap, nullTracer) import Data.Bifoldable (bifoldMap) -import Data.Dynamic (Typeable) import Data.List (intercalate) import qualified Data.List.Trace as Trace import Data.Map (Map) @@ -28,6 +27,7 @@ import Data.Monoid (Sum (..)) import Data.Set (Set) import qualified Data.Set as Set import Data.Time (secondsToDiffTime) +import Data.Typeable (Typeable) import Data.Void (Void) import Data.Word (Word32) @@ -37,46 +37,34 @@ import System.Random (mkStdGen) import qualified Network.DNS.Types as DNS import Ouroboros.Network.ConnectionHandler (ConnectionHandlerTrace) +import Ouroboros.Network.ConnectionId import Ouroboros.Network.ConnectionManager.Types import Ouroboros.Network.Diffusion.P2P (TracersExtra (..)) import qualified Ouroboros.Network.Diffusion.P2P as Diff.P2P import Ouroboros.Network.InboundGovernor hiding (TrUnexpectedlyFalseAssertion) import qualified Ouroboros.Network.PeerSelection.EstablishedPeers as EstablishedPeers -import Ouroboros.Network.PeerSelection.Governor - (DebugPeerSelection (..), TracePeerSelection (..)) +import Ouroboros.Network.PeerSelection.Governor hiding + (PeerSelectionState (..)) import qualified Ouroboros.Network.PeerSelection.Governor as Governor import qualified Ouroboros.Network.PeerSelection.LocalRootPeers as LocalRootPeers import Ouroboros.Network.PeerSelection.PeerStateActions - (PeerSelectionActionsTrace (..)) import Ouroboros.Network.PeerSelection.RootPeersDNS - (TraceLocalRootPeers (..), TracePublicRootPeers (..), - dapDomain) import Ouroboros.Network.PeerSelection.RootPeersDNS.DNSActions - (DNSorIOError (DNSError)) -import Ouroboros.Network.PeerSelection.Types (PeerStatus (..)) +import Ouroboros.Network.PeerSelection.Types import Ouroboros.Network.Server2 (ServerTrace (..)) import Ouroboros.Network.Testing.Data.AbsBearerInfo - (AbsBearerInfo (..), NonFailingAbsBearerInfo (unNFBI), - attenuation, delay, toSduSize) +import Ouroboros.Network.Testing.Data.Script (singletonScript) import Ouroboros.Network.Testing.Data.Signal (Events, Signal, eventsToList, signalProperty) import qualified Ouroboros.Network.Testing.Data.Signal as Signal -import Ouroboros.Network.Testing.Utils (WithName (..), WithTime (..), - sayTracer, splitWithNameTrace, tracerWithName, - tracerWithTime) +import Ouroboros.Network.Testing.Utils hiding (debugTracer) import Simulation.Network.Snocket (BearerInfo (..)) import Test.Ouroboros.Network.Diffusion.Node.NodeKernel import Test.Ouroboros.Network.Testnet.Simulation.Node - (DiffusionScript (..), DiffusionSimulationTrace (..), - HotDiffusionScript (HotDiffusionScript), - diffusionSimulation, - prop_diffusionScript_commandScript_valid, - prop_diffusionScript_fixupCommands) -import Test.QuickCheck (Property, checkCoverage, classify, conjoin, - counterexample, coverTable, property, tabulate) +import Test.QuickCheck import Test.Tasty import Test.Tasty.QuickCheck (testProperty) @@ -96,65 +84,71 @@ import TestLib.Utils (AllProperty (..), TestProperty (..), tests :: TestTree tests = testGroup "Ouroboros.Network.Testnet" - [ testGroup "multinodeSim" + [ testGroup "generators" [ testProperty "diffusionScript fixupCommands idempotent" - prop_diffusionScript_fixupCommands + prop_diffusionScript_fixupCommands , testProperty "diffusionScript command script valid" prop_diffusionScript_commandScript_valid + ] #if !defined(mingw32_HOST_OS) - , testProperty "diffusion no livelock" - prop_diffusion_nolivelock - , testProperty "diffusion dns can recover from fails" - prop_diffusion_dns_can_recover - , testProperty "diffusion target established public" - prop_diffusion_target_established_public - , testProperty "diffusion target active public" - prop_diffusion_target_active_public - , testProperty "diffusion target established local" - prop_diffusion_target_established_local - , testProperty "diffusion target active local" - prop_diffusion_target_active_local - , testProperty "diffusion target active root" - prop_diffusion_target_active_root - , testProperty "diffusion target active below" - prop_diffusion_target_active_below - , testProperty "diffusion target active local above" - prop_diffusion_target_active_local_above - , testProperty "diffusion connection manager valid transitions" - prop_diffusion_cm_valid_transitions - , testProperty "diffusion connection manager valid transition order" - prop_diffusion_cm_valid_transition_order - , testProperty "diffusion inbound governor valid transitions" - prop_diffusion_ig_valid_transitions - , testProperty "diffusion inbound governor valid transition order" - prop_diffusion_ig_valid_transition_order - , testProperty "diffusion cm & ig timeouts enforced" - prop_diffusion_timeouts_enforced + , testProperty "no livelock" + prop_diffusion_nolivelock + , testProperty "dns can recover from fails" + prop_diffusion_dns_can_recover + , testProperty "target established public" + prop_diffusion_target_established_public + , testProperty "target active public" + prop_diffusion_target_active_public + , testProperty "target established local" + prop_diffusion_target_established_local + , testProperty "target active local" + prop_diffusion_target_active_local + , testProperty "target active root" + prop_diffusion_target_active_root + , testProperty "target active below" + prop_diffusion_target_active_below + , testProperty "target active local below" + prop_diffusion_target_active_local_below + , testProperty "async demotion" + prop_diffusion_async_demotions + , testProperty "async demotion (unit)" + unit_diffusion_async_demotions + , testProperty "target active local above" + prop_diffusion_target_active_local_above + , testProperty "connection manager valid transitions" + prop_diffusion_cm_valid_transitions + , testProperty "connection manager valid transition order" + prop_diffusion_cm_valid_transition_order + , testProperty "inbound governor valid transitions" + prop_diffusion_ig_valid_transitions + , testProperty "inbound governor valid transition order" + prop_diffusion_ig_valid_transition_order + , testProperty "cm & ig timeouts enforced" + prop_diffusion_timeouts_enforced #endif - ] #if !defined(mingw32_HOST_OS) , testGroup "coverage" - [ testProperty "diffusion server trace coverage" + [ testProperty "server trace coverage" prop_server_trace_coverage - , testProperty "diffusion peer selection actions trace coverage" + , testProperty "peer selection actions trace coverage" prop_peer_selection_action_trace_coverage - , testProperty "diffusion peer selection trace coverage" + , testProperty "peer selection trace coverage" prop_peer_selection_trace_coverage - , testProperty "diffusion connection manager trace coverage" + , testProperty "connection manager trace coverage" prop_connection_manager_trace_coverage - , testProperty "diffusion connection manager transitions coverage" + , testProperty "connection manager transitions coverage" prop_connection_manager_transitions_coverage - , testProperty "diffusion inbound governor trace coverage" + , testProperty "inbound governor trace coverage" prop_inbound_governor_trace_coverage - , testProperty "diffusion inbound governor transitions coverage" + , testProperty "inbound governor transitions coverage" prop_inbound_governor_transitions_coverage ] , testGroup "hot diffusion script" - [ testProperty "hot diffusion target active public" + [ testProperty "target active public" prop_hot_diffusion_target_active_public - , testProperty "hot diffusion target active local" + , testProperty "target active local" prop_hot_diffusion_target_active_local - , testProperty "hot diffusion target active root" + , testProperty "target active root" prop_hot_diffusion_target_active_root ] #endif @@ -183,8 +177,19 @@ data DiffusionTestTrace = (RemoteTransitionTrace NtNAddr) | DiffusionInboundGovernorTrace (InboundGovernorTrace NtNAddr) | DiffusionServerTrace (ServerTrace NtNAddr) + | DiffusionDebugTrace String deriving (Show) + +-- | A debug tracer which embeds events in DiffusionTestTrace. +-- +debugTracer :: forall s. Tracer (IOSim s) (WithName NtNAddr String) +debugTracer = tracerWithTime + $ fmap (fmap DiffusionDebugTrace) `contramap` tracer + where + tracer :: Tracer (IOSim s) (WithTime (WithName NtNAddr DiffusionTestTrace)) + tracer = Tracer traceM + tracersExtraWithTimeName :: NtNAddr -> Diff.P2P.TracersExtra NtNAddr NtNVersion NtNVersionData @@ -261,12 +266,12 @@ tracersExtraWithTimeName ntnAddr = voidDebugPeerSelection (TraceGovernorState btime wtime state) = TraceGovernorState btime wtime (const () <$> state) -tracerDiffusionSimWithTimeName :: NtNAddr -> Tracer (IOSim s) DiffusionSimulationTrace -tracerDiffusionSimWithTimeName ntnAddr = - contramap DiffusionDiffusionSimulationTrace - . tracerWithName ntnAddr - . tracerWithTime - $ dynamicTracer + +tracerDiffusionSimWithTimeName :: Tracer (IOSim s) (WithName NtNAddr DiffusionSimulationTrace) +tracerDiffusionSimWithTimeName = tracerWithTime tracer + where + tracer :: Tracer (IOSim s) (WithTime (WithName NtNAddr DiffusionSimulationTrace)) + tracer = dynamicTracer -- | This test coverage of ServerTrace constructors, namely accept errors. @@ -281,6 +286,7 @@ prop_connection_manager_trace_coverage defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [ConnectionManagerTrace NtNAddr @@ -317,6 +323,7 @@ prop_connection_manager_transitions_coverage defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [AbstractTransitionTrace NtNAddr] events = mapMaybe (\case DiffusionConnectionManagerTransitionTrace st -> @@ -354,6 +361,7 @@ prop_inbound_governor_trace_coverage defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [InboundGovernorTrace NtNAddr] events = mapMaybe (\case DiffusionInboundGovernorTrace st -> Just st @@ -387,6 +395,7 @@ prop_inbound_governor_transitions_coverage defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [RemoteTransitionTrace NtNAddr] events = mapMaybe (\case DiffusionInboundGovernorTransitionTrace st -> @@ -423,6 +432,7 @@ prop_server_trace_coverage defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [ServerTrace NtNAddr] events = mapMaybe (\case DiffusionServerTrace st -> Just st @@ -456,6 +466,7 @@ prop_peer_selection_action_trace_coverage defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [PeerSelectionActionsTrace NtNAddr] events = mapMaybe (\case DiffusionPeerSelectionActionsTrace st -> Just st @@ -499,6 +510,7 @@ prop_peer_selection_trace_coverage defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [TracePeerSelection NtNAddr] events = mapMaybe (\case DiffusionPeerSelectionTrace st -> Just st @@ -596,6 +608,7 @@ prop_diffusion_nolivelock defaultBearerInfo diffScript@(DiffusionScript _ l) = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer trace :: [(Time, ThreadId, Maybe ThreadLabel, SimEventType)] trace = take 125000 @@ -666,6 +679,7 @@ prop_diffusion_dns_can_recover defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [Events DiffusionTestTrace] events = fmap ( Signal.eventsFromList @@ -786,6 +800,7 @@ prop_diffusion_target_established_public defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [Events DiffusionTestTrace] events = fmap ( Signal.eventsFromList @@ -880,6 +895,7 @@ prop_diffusion_target_active_public defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [Events DiffusionTestTrace] events = fmap ( Signal.eventsFromList @@ -960,6 +976,7 @@ prop_diffusion_target_active_local defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [Events DiffusionTestTrace] events = fmap ( Signal.eventsFromList @@ -1040,6 +1057,7 @@ prop_diffusion_target_active_root defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [Events DiffusionTestTrace] events = fmap ( Signal.eventsFromList @@ -1161,6 +1179,7 @@ prop_diffusion_target_established_local defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [Events DiffusionTestTrace] events = fmap ( Signal.eventsFromList @@ -1320,6 +1339,7 @@ prop_diffusion_target_active_below defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [Events DiffusionTestTrace] events = fmap ( Signal.eventsFromList @@ -1455,6 +1475,281 @@ prop_diffusion_target_active_below defaultBearerInfo diffScript = (\toolong -> Set.null toolong) promotionOpportunitiesIgnoredTooLong + +prop_diffusion_target_active_local_below :: AbsBearerInfo + -> DiffusionScript + -> Property +prop_diffusion_target_active_local_below defaultBearerInfo diffScript = + let sim :: forall s . IOSim s Void + sim = diffusionSimulation (toBearerInfo defaultBearerInfo) + diffScript + tracersExtraWithTimeName + tracerDiffusionSimWithTimeName + nullTracer + + events :: [Events DiffusionTestTrace] + events = fmap ( Signal.eventsFromList + . fmap (\(WithName _ (WithTime t b)) -> (t, b)) + ) + . Trace.toList + . splitWithNameTrace + . Trace.fromList () + . fmap snd + . Signal.eventsToList + . Signal.eventsFromListUpToTime (Time (10 * 60 * 60)) + . Trace.toList + . fmap (\(WithTime t (WithName name b)) -> (t, WithName name (WithTime t b))) + . withTimeNameTraceEvents + @DiffusionTestTrace + @NtNAddr + . Trace.fromList (MainReturn (Time 0) () []) + . fmap (\(t, tid, tl, te) -> SimEvent t tid tl te) + . take 125000 + . traceEvents + $ runSimTrace sim + + in conjoin + $ (\ev -> + let evsList = eventsToList ev + lastTime = fst + . last + $ evsList + in classifySimulatedTime lastTime + $ classifyNumberOfEvents (length evsList) + $ verify_target_active_below ev + ) + <$> events + + where + verify_target_active_below :: Events DiffusionTestTrace -> Property + verify_target_active_below events = + let govLocalRootPeersSig :: Signal (LocalRootPeers.LocalRootPeers NtNAddr) + govLocalRootPeersSig = + selectDiffusionPeerSelectionState Governor.localRootPeers events + + govEstablishedPeersSig :: Signal (Set NtNAddr) + govEstablishedPeersSig = + selectDiffusionPeerSelectionState + (EstablishedPeers.toSet . Governor.establishedPeers) + events + + govActivePeersSig :: Signal (Set NtNAddr) + govActivePeersSig = + selectDiffusionPeerSelectionState Governor.activePeers events + + govActiveFailuresSig :: Signal (Set NtNAddr) + govActiveFailuresSig = + Signal.keyedLinger + 180 -- 3 minutes -- TODO: too eager to reconnect? + (fromMaybe Set.empty) + . Signal.fromEvents + . Signal.selectEvents + (\case TracePromoteWarmFailed _ _ peer _ -> + --TODO: the simulation does not yet cause this to happen + Just (Set.singleton peer) + TraceDemoteAsynchronous status + | Set.null failures -> Nothing + | otherwise -> Just failures + where + -- unlike in the governor case we take into account + -- all asynchronous demotions + failures = Map.keysSet status + _ -> Nothing + ) + . selectDiffusionPeerSelectionEvents + $ events + + promotionOpportunities :: Signal (Set NtNAddr) + promotionOpportunities = + (\local established active recentFailures -> + Set.unions + [ -- There are no opportunities if we're at or above target + if Set.size groupActive >= target + then Set.empty + else groupEstablished Set.\\ active + Set.\\ recentFailures + | (target, group) <- LocalRootPeers.toGroupSets local + , let groupActive = group `Set.intersection` active + groupEstablished = group `Set.intersection` established + ] + ) <$> govLocalRootPeersSig + <*> govEstablishedPeersSig + <*> govActivePeersSig + <*> govActiveFailuresSig + + promotionOpportunitiesIgnoredTooLong :: Signal (Set NtNAddr) + promotionOpportunitiesIgnoredTooLong = + Signal.keyedTimeout + 10 -- seconds + id + promotionOpportunities + + in counterexample + ("\nSignal key: (local, established peers, active peers, " ++ + "recent failures, opportunities, ignored too long)") $ + + signalProperty 20 show + (\(_,_,_,_,_,toolong) -> Set.null toolong) + ((,,,,,) <$> (LocalRootPeers.toGroupSets <$> govLocalRootPeersSig) + <*> govEstablishedPeersSig + <*> govActivePeersSig + <*> govActiveFailuresSig + <*> promotionOpportunities + <*> promotionOpportunitiesIgnoredTooLong) + + +-- | A testing scenario which reproduces issue #4046 +-- +async_demotion_network_script :: DiffusionScript +async_demotion_network_script = + DiffusionScript + simArgs + [ ( common { naAddr = addr1, + naLocalRootPeers = localRoots1, + naLocalSelectionTargets = Governor.PeerSelectionTargets 0 2 2 2 } + , [ JoinNetwork 0 (Just addr1) + -- reconfigure the peer to trigger the outbound governor log + , Reconfigure 240 localRoots1' + ] + ) + , ( common { naAddr = addr2, + naLocalRootPeers = [(1, Map.fromList [(ra_addr1, DoNotAdvertisePeer)])] } + , [JoinNetwork 0 (Just addr2), Kill 5, JoinNetwork 20 (Just addr2)] + ) + , ( common { naAddr = addr3, + naLocalRootPeers = [(1, Map.fromList [(ra_addr1, DoNotAdvertisePeer)])] } + , [JoinNetwork 0 (Just addr3)] + ) + ] + where + addr1 = TestAddress (IPAddr (read "10.0.0.1") 3000) + ra_addr1 = RelayAccessAddress (read "10.0.0.1") 3000 + localRoots1 = [(2, Map.fromList [(ra_addr2, DoNotAdvertisePeer) + ,(ra_addr3, DoNotAdvertisePeer)])] + localRoots1' = [(2, Map.fromList [(ra_addr2, DoAdvertisePeer) + ,(ra_addr3, DoAdvertisePeer)])] + + addr2 = TestAddress (IPAddr (read "10.0.0.2") 3000) + ra_addr2 = RelayAccessAddress (read "10.0.0.2") 3000 + + addr3 = TestAddress (IPAddr (read "10.0.0.3") 3000) + ra_addr3 = RelayAccessAddress (read "10.0.0.3") 3000 + + simArgs = SimArgs { + saSlot = secondsToDiffTime 1, + saQuota = 5 -- 5% chance of producing a block + } + common = NodeArgs { + naSeed = 10, + naMbTime = Just 1, + naRelays = [], + naDomainMap = Map.empty, + naAddr = undefined, + naLocalRootPeers = undefined, + naLocalSelectionTargets + = Governor.PeerSelectionTargets 0 1 1 1, + naDNSTimeoutScript = singletonScript (DNSTimeout 3), + naDNSLookupDelayScript + = singletonScript (DNSLookupDelay 0.2) + } + + +-- | Show that outbound governor reacts to asynchronous demotions +-- +prop_diffusion_async_demotions :: AbsBearerInfo + -> DiffusionScript + -> Property +prop_diffusion_async_demotions defaultBearerInfo diffScript = + let sim :: forall s . IOSim s Void + sim = diffusionSimulation (toBearerInfo defaultBearerInfo) + diffScript + tracersExtraWithTimeName + tracerDiffusionSimWithTimeName + debugTracer + + events :: [Events DiffusionTestTrace] + events = fmap ( Signal.eventsFromList + . fmap (\(WithName _ (WithTime t b)) -> (t, b)) + ) + . Trace.toList + . splitWithNameTrace + . Trace.fromList () + . fmap snd + . Signal.eventsToList + . Signal.eventsFromListUpToTime (Time (10 * 60 * 60)) + . Trace.toList + . fmap (\(WithTime t (WithName name b)) -> (t, WithName name (WithTime t b))) + . withTimeNameTraceEvents + @DiffusionTestTrace + @NtNAddr + . Trace.fromList (MainReturn (Time 0) () []) + . fmap (\(t, tid, tl, te) -> SimEvent t tid tl te) + . takeUntilEndofTurn 125000 + . traceEvents + $ runSimTrace sim + + in conjoin + $ (\ev -> + let evsList = eventsToList ev + lastTime = fst + . last + $ evsList + in classifySimulatedTime lastTime + $ classifyNumberOfEvents (length evsList) + $ verify_async_demotions ev + ) + <$> events + + where + verify_async_demotions :: Events DiffusionTestTrace -> Property + verify_async_demotions events = + + let demotionOpportunities :: Signal (Set NtNAddr) + demotionOpportunities = + Signal.keyedUntil + (\case Right a -> a + _ -> Set.empty) + (\case Left (Just a) -> a + _ -> Set.empty) + (\case Left Nothing -> True + _ -> False) + . Signal.fromEventsWith (Right Set.empty) + . Signal.selectEvents + (\case DiffusionPeerSelectionActionsTrace (PeerStatusChanged (HotToCold connId)) -> + Just $ Right demotions + where + demotions = Set.singleton (remoteAddress connId) + DiffusionPeerSelectionTrace (TraceDemoteAsynchronous status) -> + Just $ Left (Just failures) + where + failures = Map.keysSet (Map.filter ((==PeerCold) . fst) status) + DiffusionPeerSelectionTrace (TraceDemoteHotFailed _ _ peeraddr _) -> + Just $ Left (Just failures) + where + failures = Set.singleton peeraddr + DiffusionConnectionManagerTrace TrShutdown -> + Just $ Left Nothing + _ -> Nothing + ) + $ events + + demotionOpportunitiesTooLong :: Signal (Set NtNAddr) + demotionOpportunitiesTooLong = + Signal.keyedTimeout 1 id demotionOpportunities + + in signalProperty + 20 show Set.null + demotionOpportunitiesTooLong + + +unit_diffusion_async_demotions :: Property +unit_diffusion_async_demotions = + prop_diffusion_async_demotions + absNoAttenuation + async_demotion_network_script + + + -- | A variant of -- 'Test.Ouroboros.Network.PeerSelection.prop_governor_target_active_local_above' -- but for running on Diffusion. This means it has to have in consideration the @@ -1470,6 +1765,7 @@ prop_diffusion_target_active_local_above defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + debugTracer events :: [Events DiffusionTestTrace] events = fmap ( Signal.eventsFromList @@ -1592,6 +1888,7 @@ prop_diffusion_cm_valid_transitions defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [Trace () (WithName NtNAddr (WithTime DiffusionTestTrace))] events = fmap (Trace.fromList ()) @@ -1693,6 +1990,7 @@ prop_diffusion_cm_valid_transition_order defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [Trace () (WithName NtNAddr (WithTime DiffusionTestTrace))] events = fmap (Trace.fromList ()) @@ -1755,6 +2053,7 @@ prop_diffusion_ig_valid_transitions defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [Trace () (WithName NtNAddr (WithTime DiffusionTestTrace))] events = fmap (Trace.fromList ()) @@ -1825,6 +2124,7 @@ prop_diffusion_ig_valid_transition_order defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [Trace () (WithName NtNAddr (WithTime DiffusionTestTrace))] events = fmap (Trace.fromList ()) @@ -1892,6 +2192,7 @@ prop_diffusion_timeouts_enforced defaultBearerInfo diffScript = diffScript tracersExtraWithTimeName tracerDiffusionSimWithTimeName + nullTracer events :: [Trace () (Time, DiffusionTestTrace)] events = fmap ( Trace.fromList () @@ -2056,3 +2357,18 @@ toBearerInfo abi = biSDUSize = toSduSize (abiSDUSize abi) } + +-- | Like 'take' but includes all the traces of the timestamp at the given +-- index. +-- +takeUntilEndofTurn :: Int + -> [(Time, ThreadId, Maybe ThreadLabel, SimEventType)] + -> [(Time, ThreadId, Maybe ThreadLabel, SimEventType)] +takeUntilEndofTurn n as = + case splitAt n as of + ([], _) -> [] + (hs, ts) -> + hs ++ takeWhile (\(t,_,_,_) -> t <= tmax) ts + where + tmax :: Time + tmax = case last hs of (t,_,_,_) -> t diff --git a/ouroboros-network/test/Test/Ouroboros/Network/Testnet/Simulation/Node.hs b/ouroboros-network/test/Test/Ouroboros/Network/Testnet/Simulation/Node.hs index 4b0193f8ae0..75bffa023ac 100644 --- a/ouroboros-network/test/Test/Ouroboros/Network/Testnet/Simulation/Node.hs +++ b/ouroboros-network/test/Test/Ouroboros/Network/Testnet/Simulation/Node.hs @@ -1,4 +1,6 @@ {-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE QuantifiedConstraints #-} {-# LANGUAGE RankNTypes #-} @@ -8,6 +10,7 @@ module Test.Ouroboros.Network.Testnet.Simulation.Node ( SimArgs (..) + , NodeArgs (..) , DiffusionScript (..) , HotDiffusionScript (..) , DiffusionSimulationTrace (..) @@ -27,13 +30,14 @@ import Control.Monad (forM, replicateM, (>=>)) import Control.Monad.Class.MonadAsync (MonadAsync (Async, cancel, waitAny, withAsync)) import Control.Monad.Class.MonadFork (MonadFork) +import Control.Monad.Class.MonadSay import Control.Monad.Class.MonadST (MonadST) import Control.Monad.Class.MonadThrow (MonadCatch, MonadEvaluate, MonadMask, MonadThrow, SomeException) import Control.Monad.Class.MonadTime (DiffTime, MonadTime) import Control.Monad.Class.MonadTimer (MonadTimer, threadDelay) import Control.Monad.Fix (MonadFix) -import Control.Tracer (Tracer, nullTracer, traceWith) +import Control.Tracer (Tracer (..), contramap, nullTracer, traceWith) import qualified Data.ByteString.Lazy as BL import Data.Foldable (traverse_) @@ -41,6 +45,7 @@ import Data.IP (IP (..), toIPv4, toIPv6) import Data.List (delete, intercalate, nub, (\\)) import Data.Map (Map) import qualified Data.Map as Map +import Data.Maybe (fromMaybe) import Data.Set (Set) import qualified Data.Set as Set import Data.Time.Clock (secondsToDiffTime) @@ -50,6 +55,9 @@ import System.Random (StdGen, mkStdGen) import Network.DNS (Domain, TTL) +import Network.TypedProtocol.Core (PeerHasAgency (..)) +import qualified Network.TypedProtocol.PingPong.Type as PingPong + import qualified Ouroboros.Network.Diffusion.P2P as Diff.P2P import Ouroboros.Network.Driver.Limits (ProtocolSizeLimits (..), ProtocolTimeLimits (..)) @@ -79,8 +87,10 @@ import Ouroboros.Network.Snocket (Snocket, TestAddress (..)) import Ouroboros.Network.Testing.ConcreteBlock (Block) import Ouroboros.Network.Testing.Data.Script (Script (..)) -import Ouroboros.Network.Testing.Utils (genDelayWithPrecision) -import Simulation.Network.Snocket (BearerInfo (..), FD, withSnocket) +import Ouroboros.Network.Testing.Utils (WithName (..), + genDelayWithPrecision, tracerWithName) +import Simulation.Network.Snocket (BearerInfo (..), FD, SnocketTrace, + WithAddr (..), withSnocket) import qualified Test.Ouroboros.Network.Diffusion.Node as NodeKernel import Test.Ouroboros.Network.Diffusion.Node.NodeKernel @@ -544,6 +554,7 @@ diffusionSimulation :: forall m. ( MonadAsync m , MonadFix m , MonadFork m + , MonadSay m , MonadST m , MonadEvaluate m , MonadLabelledSTM m @@ -562,15 +573,16 @@ diffusionSimulation -> Diff.P2P.TracersExtra NtNAddr NtNVersion NtNVersionData NtCAddr NtCVersion NtCVersionData SomeException m ) - -> ( NtNAddr - -> Tracer m DiffusionSimulationTrace ) + -> Tracer m (WithName NtNAddr DiffusionSimulationTrace) + -> Tracer m (WithName NtNAddr String) -> m Void diffusionSimulation defaultBearerInfo (DiffusionScript simArgs nodeArgs) tracersExtraWithTimeName - diffSimTracerWithTimName = - withSnocket nullTracer defaultBearerInfo Map.empty + tracer + debugTracer = + withSnocket netSimTracer defaultBearerInfo Map.empty $ \ntnSnocket _ -> withSnocket nullTracer defaultBearerInfo Map.empty $ \ntcSnocket _ -> do @@ -585,6 +597,10 @@ diffusionSimulation (_, x) <- waitAny nodes return x where + netSimTracer :: Tracer m (WithAddr NtNAddr (SnocketTrace m NtNAddr)) + netSimTracer = (\(WithAddr l _ a) -> WithName (fromMaybe (TestAddress $ IPAddr (read "0.0.0.0") 0) l) (show a)) + `contramap` debugTracer + -- | Runs a single node according to a list of commands. runCommand :: Maybe ( Async m Void @@ -603,19 +619,19 @@ diffusionSimulation -> m Void runCommand Nothing ntnSnocket ntcSnocket dMapVarMap sArgs nArgs [] = do threadDelay 3600 - traceWith (diffSimTracerWithTimName (naAddr nArgs)) TrRunning + traceWith tracer (WithName (naAddr nArgs) TrRunning) runCommand Nothing ntnSnocket ntcSnocket dMapVarMap sArgs nArgs [] runCommand (Just (_, _)) ntnSnocket ntcSnocket dMapVarMap sArgs nArgs [] = do -- We shouldn't block this thread waiting -- on the async since this will lead to a deadlock -- as thread returns 'Void'. threadDelay 3600 - traceWith (diffSimTracerWithTimName (naAddr nArgs)) TrRunning + traceWith tracer (WithName (naAddr nArgs) TrRunning) runCommand Nothing ntnSnocket ntcSnocket dMapVarMap sArgs nArgs [] runCommand Nothing ntnSnocket ntcSnocket dMapVarMap sArgs nArgs (JoinNetwork delay Nothing:cs) = do threadDelay delay - traceWith (diffSimTracerWithTimName (naAddr nArgs)) TrJoiningNetwork + traceWith tracer (WithName (naAddr nArgs) TrJoiningNetwork) lrpVar <- newTVarIO $ naLocalRootPeers nArgs let dnsMapVar = dMapVarMap Map.! naAddr nArgs withAsync (runNode sArgs nArgs ntnSnocket ntcSnocket lrpVar dnsMapVar) $ \nodeAsync -> @@ -624,7 +640,7 @@ diffusionSimulation (JoinNetwork delay (Just ip):cs) = do threadDelay delay let nArgs' = nArgs { naAddr = ip } - traceWith (diffSimTracerWithTimName ip) TrJoiningNetwork + traceWith tracer (WithName ip TrJoiningNetwork) lrpVar <- newTVarIO $ naLocalRootPeers nArgs' -- Updating DomainMap entry now that the node is having a new IP @@ -643,7 +659,7 @@ diffusionSimulation runCommand (Just (async, _)) ntnSnocket ntcSnocket dMapVarMap sArgs nArgs (Kill delay:cs) = do threadDelay delay - traceWith (diffSimTracerWithTimName (naAddr nArgs)) TrKillingNode + traceWith tracer (WithName (naAddr nArgs) TrKillingNode) cancel async runCommand Nothing ntnSnocket ntcSnocket dMapVarMap sArgs nArgs cs runCommand _ _ _ _ _ _ (Kill _:_) = do @@ -653,7 +669,7 @@ diffusionSimulation runCommand (Just (async, lrpVar)) ntnSnocket ntcSnocket dMapVarMap sArgs nArgs (Reconfigure delay newLrp:cs) = do threadDelay delay - traceWith (diffSimTracerWithTimName (naAddr nArgs)) TrReconfigurionNode + traceWith tracer (WithName (naAddr nArgs) TrReconfigurionNode) _ <- atomically $ writeTVar lrpVar newLrp runCommand (Just (async, lrpVar)) ntnSnocket ntcSnocket dMapVarMap sArgs nArgs cs @@ -668,7 +684,7 @@ diffusionSimulation (TestAddress (IPAddr newIP _)) dMapVarMap = do threadDelay delay - traceWith (diffSimTracerWithTimName oip) TrUpdatingDNS + traceWith tracer (WithName oip TrUpdatingDNS) traverse_ (\dMapVar -> atomically $ do dnsMap <- readTVar dMapVar let dnsMap' = @@ -750,10 +766,8 @@ diffusionSimulation , NodeKernel.keepAliveSizeLimits = byteLimitsKeepAlive (const 0) , NodeKernel.keepAliveTimeLimits = timeLimitsKeepAlive , NodeKernel.pingPongLimits = defaultMiniProtocolsLimit - , NodeKernel.pingPongSizeLimits = - ProtocolSizeLimits (const smallByteLimit) (const 0) - , NodeKernel.pingPongTimeLimits = - ProtocolTimeLimits (const (Just 60)) + , NodeKernel.pingPongSizeLimits = byteLimitsPingPong + , NodeKernel.pingPongTimeLimits = timeLimitsPingPong , NodeKernel.handshakeLimits = defaultMiniProtocolsLimit , NodeKernel.handshakeTimeLimits = ProtocolSizeLimits (const (4 * 1440)) @@ -782,8 +796,8 @@ diffusionSimulation { NodeKernel.aIPAddress = rap , NodeKernel.aAcceptedLimits = acceptedConnectionsLimit , NodeKernel.aDiffusionMode = diffusionMode - , NodeKernel.aKeepAliveInterval = 0 - , NodeKernel.aPingPongInterval = 0 + , NodeKernel.aKeepAliveInterval = 10 + , NodeKernel.aPingPongInterval = 10 , NodeKernel.aPeerSelectionTargets = peerSelectionTargets , NodeKernel.aReadLocalRootPeers = readLocalRootPeers , NodeKernel.aReadPublicRootPeers = readPublicRootPeers @@ -792,9 +806,11 @@ diffusionSimulation , NodeKernel.aTimeWaitTimeout = 30 , NodeKernel.aDNSTimeoutScript = dnsTimeout , NodeKernel.aDNSLookupDelayScript = dnsLookupDelay + , NodeKernel.aDebugTracer = tracerWithName rap debugTracer } - in NodeKernel.run blockGeneratorArgs + in NodeKernel.run (WithName rap `contramap` debugTracer) + blockGeneratorArgs limitsAndTimeouts interfaces arguments @@ -819,6 +835,22 @@ diffusionSimulation ] return (Map.fromList mapDomains) +-- +-- PingPong byte & time limits +-- + +byteLimitsPingPong :: ProtocolSizeLimits PingPong.PingPong BL.ByteString +byteLimitsPingPong = ProtocolSizeLimits (const smallByteLimit) (fromIntegral . BL.length) + +timeLimitsPingPong :: ProtocolTimeLimits PingPong.PingPong +timeLimitsPingPong = ProtocolTimeLimits $ \case + ClientAgency PingPong.TokIdle -> Nothing + ServerAgency PingPong.TokBusy -> Just 60 + +-- +-- Utils +-- + ntnToPeerAddr :: IP -> PortNumber -> NtNAddr ntnToPeerAddr a b = TestAddress (IPAddr a b)