Skip to content

Commit 13e6b2f

Browse files
authored
Merge pull request #66 from IntersectMBO/coot/min-sig-delay
Added --min-sig-delay flag
2 parents 638b821 + 0f4f14e commit 13e6b2f

9 files changed

Lines changed: 144 additions & 16 deletions

File tree

dmq-node/app/Main.hs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import Data.Version (showVersion)
3333
import Data.Void (Void)
3434
import Options.Applicative
3535
import System.Directory qualified as Dir
36-
import System.Exit (die, exitSuccess)
36+
import System.Exit (die, exitFailure, exitSuccess)
3737
import System.IOManager (withIOManager)
3838
import System.Metrics qualified as EKG
3939
import System.Random qualified as Random
@@ -93,16 +93,25 @@ runDMQ commandLineConfig = do
9393
-- options
9494
let dmqConfig :: Configuration
9595
dmqConfig@Configuration {
96+
dmqcNetworkMagic = I dmqNetworkMagic,
9697
dmqcTopologyFile = I topologyFile,
9798
dmqcCardanoNodeSocket = I socketPath,
9899
dmqcVersion = I version,
99100
dmqcShelleyGenesisFile = I genesisFile,
100-
dmqcShelleyGenesisHash = I genesisHash
101+
dmqcShelleyGenesisHash = I genesisHash,
102+
dmqcMinSigDelay = I minSigDelay
103+
101104
} = fromRight mempty config'
102105
<> commandLineConfig
103106
`act`
104107
defaultConfiguration
105108

109+
validationCfg :: ValidationCfg
110+
validationCfg =
111+
ValidationCfg {
112+
vcMinSigDelay = minSigDelay
113+
}
114+
106115
when version $ do
107116
let gitrev :: Text.Text
108117
gitrev = $(gitRev)
@@ -134,6 +143,11 @@ runDMQ commandLineConfig = do
134143
)
135144
<- mkDMQTracers ekgStore configFilePath
136145

146+
when (validationCfg /= Policy.defaultValidationCfg) $ do
147+
traceWith dmqStartupTracer (DMQValidationCfgWarning dmqNetworkMagic validationCfg)
148+
-- one cannot run on mainnet with a custom `ValidationCfg`
149+
unless (dmqNetworkMagic == Policy.dmqMainnetNetworkMagic)
150+
exitFailure
137151

138152
case config' of
139153
Left e -> traceWith dmqStartupTracer (DMQConfigurationError e)
@@ -193,7 +207,11 @@ runDMQ commandLineConfig = do
193207
Mempool.getWriter SigDuplicate
194208
sigId
195209
(\(utcNow, now) sigs ->
196-
withPoolValidationCtx (stakePools nodeKernel) utcNow now (validateSig sigs)
210+
withPoolValidationCtx
211+
(stakePools nodeKernel)
212+
utcNow
213+
now
214+
(validateSig validationCfg sigs)
197215
)
198216
(traverse_ $ \(sigid, reason) -> do
199217
traceWith sigValidationTracer $ InvalidSignature sigid reason
@@ -222,7 +240,11 @@ runDMQ commandLineConfig = do
222240
Mempool.getWriter SigDuplicate
223241
sigId
224242
(\(utcNow, now) sigs ->
225-
withPoolValidationCtx (stakePools nodeKernel) utcNow now (validateSig sigs)
243+
withPoolValidationCtx
244+
(stakePools nodeKernel)
245+
utcNow
246+
now
247+
(validateSig validationCfg sigs)
226248
)
227249
(traverse_ $ \(sigid, reason) ->
228250
traceWith localSigValidationTracer $ InvalidSignature sigid reason
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!--
2+
A new scriv changelog fragment.
3+
4+
Uncomment the section that is right (remove the HTML comment wrapper).
5+
For top level release notes, leave all the headers commented out.
6+
-->
7+
8+
<!--
9+
### Breaking
10+
11+
- A bullet item for the Breaking category.
12+
13+
-->
14+
### Non-Breaking
15+
16+
- Added `--min-sig-delay` internal flag. One cannot use it on the mainnet.
17+
18+
<!--
19+
### Patch
20+
21+
- A bullet item for the Patch category.
22+
23+
-->

dmq-node/src/DMQ/Configuration.hs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ import Ouroboros.Network.Snocket (LocalAddress (..), RemoteAddress)
7676

7777
import DMQ.Configuration.Topology (NoExtraConfig (..), NoExtraFlags (..))
7878
import DMQ.Genesis
79+
import DMQ.Policy qualified as Policy
7980

8081
-- | Configuration comes in two flavours depending on the `f` functor:
8182
-- `PartialConfig` is using `Last` and `Configuration` is using an identity
@@ -136,6 +137,10 @@ data Configuration' f =
136137
dmqcTargetOfEstablishedBigLedgerPeers :: f Int,
137138
dmqcTargetOfActiveBigLedgerPeers :: f Int,
138139

140+
-- | Minimal delay between signatures from the same peer.
141+
--
142+
dmqcMinSigDelay :: f DiffTime,
143+
139144
-- | CLI only option to show version and exit.
140145
dmqcVersion :: f Bool
141146
}
@@ -195,7 +200,7 @@ defaultConfiguration = Configuration {
195200
dmqcIPv6 = I Nothing,
196201
dmqcLocalAddress = I (LocalAddress "dmq-node.socket"),
197202
-- mainnet dmq protocol magic according to CIP#137
198-
dmqcNetworkMagic = I NetworkMagic { unNetworkMagic = 2_912_307_721 },
203+
dmqcNetworkMagic = I Policy.dmqMainnetNetworkMagic,
199204
dmqcCardanoNetworkMagic =
200205
I (NetworkMagic . unProtocolMagicId $ mainnetProtocolMagicId),
201206
dmqcPortNumber = I 3_141,
@@ -218,6 +223,8 @@ defaultConfiguration = Configuration {
218223
dmqcPeerSharing = I PeerSharingEnabled,
219224
dmqcLedgerPeers = I False,
220225

226+
dmqcMinSigDelay = I Policy.minSigDelay,
227+
221228
-- CLI only options
222229
dmqcVersion = I False
223230
}
@@ -271,6 +278,9 @@ instance FromJSON PartialConfig where
271278
dmqcProtocolIdleTimeout <- Last <$> v .:? "ProtocolIdleTimeout"
272279
dmqcChurnInterval <- Last <$> v .:? "ChurnInterval"
273280

281+
-- not configurable in a config file
282+
let dmqcMinSigDelay = Last Nothing
283+
274284
pure $
275285
Configuration
276286
{ dmqcIPv4 = Last dmqcIPv4

dmq-node/src/DMQ/Configuration/CLIOptions.hs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ parseCLIOptions =
9797
<> help "Show dmq-node version"
9898
)
9999
)
100+
<*> optional (
101+
option auto
102+
( long "min-sig-delay"
103+
<> internal
104+
)
105+
)
100106
where
101107
-- NOTE: we cannot simply use `value <> showDefault`, because configuration
102108
-- will always overwrite values provided by configuration file.
@@ -108,9 +114,15 @@ parseCLIOptions =
108114
, Help.paragraph ("(default: " ++ show a ++ ")")
109115
]
110116

111-
mkConfiguration ipv4 ipv6 portNumber localAddress
112-
configFile topologyFile cardanoNodeSocket cardanoNetworkMagic dmqNetworkMagic
113-
version =
117+
mkConfiguration ipv4 ipv6 portNumber
118+
localAddress
119+
configFile
120+
topologyFile
121+
cardanoNodeSocket
122+
cardanoNetworkMagic
123+
dmqNetworkMagic
124+
version
125+
minSigDelay =
114126
mempty { dmqcIPv4 = Last (Just <$> ipv4),
115127
dmqcIPv6 = Last (Just <$> ipv6),
116128
dmqcLocalAddress = Last (LocalAddress <$> localAddress),
@@ -120,5 +132,6 @@ parseCLIOptions =
120132
dmqcCardanoNodeSocket = Last cardanoNodeSocket,
121133
dmqcCardanoNetworkMagic = Last (NetworkMagic <$> cardanoNetworkMagic),
122134
dmqcNetworkMagic = Last (NetworkMagic <$> dmqNetworkMagic),
123-
dmqcVersion = Last version
135+
dmqcVersion = Last version,
136+
dmqcMinSigDelay = Last minSigDelay
124137
}

dmq-node/src/DMQ/Diffusion/NodeKernel/Types.hs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
1-
{-# LANGUAGE DataKinds #-}
2-
{-# LANGUAGE RankNTypes #-}
1+
{-# LANGUAGE DataKinds #-}
2+
{-# LANGUAGE OverloadedStrings #-}
3+
{-# LANGUAGE RankNTypes #-}
34

45
module DMQ.Diffusion.NodeKernel.Types
56
( NodeKernel (..)
67
, Readiness (..)
78
, PoolId
89
, StakePools (..)
910
, PoolValidationCtx (..)
11+
, ValidationCfg (..)
1012
) where
1113

1214
import Control.Concurrent.Class.MonadSTM.Strict
1315
import Control.Monad.Class.MonadTime.SI
1416

17+
import Data.Aeson qualified as Aeson
1518
import Data.Map.Strict (Map)
1619
import Data.OrdPSQ (OrdPSQ)
1720
import Data.Word
@@ -104,3 +107,16 @@ data PoolValidationCtx =
104107
-- signatures
105108
}
106109
deriving Show
110+
111+
112+
newtype ValidationCfg = ValidationCfg {
113+
vcMinSigDelay :: DiffTime
114+
-- ^ minimal delay between signatures created by the same SPO. It can be
115+
-- modified with an internal CLI option. The default value is
116+
-- `DMQ.Policy.minSigDelay`.
117+
}
118+
deriving Eq
119+
120+
instance Aeson.ToJSON ValidationCfg where
121+
toJSON ValidationCfg { vcMinSigDelay } =
122+
Aeson.object [ "minSigDelay" Aeson..= vcMinSigDelay ]

dmq-node/src/DMQ/Policy.hs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
{-# LANGUAGE NumericUnderscores #-}
2+
13
module DMQ.Policy
24
( sigDecisionPolicy
35
, sigSubmissionIngressLimit
@@ -9,17 +11,21 @@ module DMQ.Policy
911
, maxSigExpiresAtDelay
1012
, maxSigIdsInflight
1113
, cardanoEpochSlots
14+
, defaultValidationCfg
15+
, dmqMainnetNetworkMagic
1216
) where
1317

1418
import Data.Time (DiffTime, NominalDiffTime)
1519

1620
import Cardano.Chain.Slotting (EpochSlots (..))
1721

22+
import DMQ.Diffusion.NodeKernel.Types (ValidationCfg (..))
1823
import DMQ.Diffusion.PeerSelection.PeerMetric (PeerMetricConfiguration (..))
1924
import DMQ.Protocol.SigSubmission.Type (NumTxIdsToReq)
2025

2126
import Network.Mux.Types (MiniProtocolLimits (..))
2227

28+
import Ouroboros.Network.Magic (NetworkMagic (..))
2329
import Ouroboros.Network.SizeInBytes (SizeInBytes)
2430
import Ouroboros.Network.TxSubmission.Inbound.V2
2531

@@ -55,6 +61,12 @@ maxSigExpiresAtDelay :: NominalDiffTime
5561
maxSigExpiresAtDelay = 1800
5662

5763

64+
defaultValidationCfg :: ValidationCfg
65+
defaultValidationCfg = ValidationCfg {
66+
vcMinSigDelay = minSigDelay
67+
}
68+
69+
5870
-- | Maximum numbers signatures in-flight per peer.
5971
--
6072
-- NOTE: it is used by:
@@ -128,3 +140,9 @@ cardanoEpochSlots :: EpochSlots
128140
cardanoEpochSlots = EpochSlots $ 10 * k
129141
where
130142
k = 2160
143+
144+
145+
-- | Mainnet `NetworkMagic` for dmq according to CIP#0137.
146+
--
147+
dmqMainnetNetworkMagic :: NetworkMagic
148+
dmqMainnetNetworkMagic = NetworkMagic 2_912_307_721

dmq-node/src/DMQ/Protocol/SigSubmission/Validate.hs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ module DMQ.Protocol.SigSubmission.Validate
1515
, SigValidationException (..)
1616
, SigValidationError (..)
1717
, SigValidationTrace (..)
18+
, ValidationCfg (..)
1819
) where
1920

2021
import Control.Monad.Class.MonadTime.SI
@@ -41,7 +42,8 @@ import Cardano.Ledger.Api.State.Query (StakeSnapshot (ssSetPool))
4142
import Cardano.Ledger.BaseTypes.NonZero qualified as Ledger
4243
import Cardano.Ledger.Keys qualified as Ledger
4344

44-
import DMQ.Diffusion.NodeKernel (PoolValidationCtx (..), Readiness (..))
45+
import DMQ.Diffusion.NodeKernel (PoolValidationCtx (..), Readiness (..),
46+
ValidationCfg (..))
4547
import DMQ.Policy qualified as Policy
4648
import DMQ.Protocol.SigSubmission.Type
4749

@@ -62,17 +64,20 @@ validateSigId Sig { sigId = SigId hash, sigSignedBytes } =
6264
castHash (hashWith id (LBS.toStrict sigSignedBytes))
6365

6466

67+
6568
validateSig :: forall crypto.
6669
( Crypto crypto
6770
, DSIGN crypto ~ Ledger.DSIGN
6871
, DSIGN.Signable (DSIGN crypto) (OCertSignable crypto)
6972
, ContextKES (KES crypto) ~ ()
7073
, Signable (KES crypto) ByteString
7174
)
72-
=> [Sig crypto]
75+
=> ValidationCfg
76+
-- ^ minimum signature delay produced by the same stake pool
77+
-> [Sig crypto]
7378
-> PoolValidationCtx
7479
-> ([Either (SigId, SigValidationError) (Sig crypto)], PoolValidationCtx)
75-
validateSig sigs = State.runState (traverse (commute . validate) sigs)
80+
validateSig ValidationCfg { vcMinSigDelay } sigs = State.runState (traverse (commute . validate) sigs)
7681
where
7782
-- Commute `StateT` and `ExceptT` monads, e.g. a natural transformation
7883
-- `StateT s (Except e) ~> ExceptT e (State s)`. The latter monad allows us
@@ -127,7 +132,7 @@ validateSig sigs = State.runState (traverse (commute . validate) sigs)
127132
= (Right (), Just (now, ()))
128133

129134
fn a@(Just (lastSeen, _))
130-
| sinceLast >= Policy.minSigDelay
135+
| sinceLast >= vcMinSigDelay
131136
= (Right (), Just (now, ()))
132137

133138
| otherwise

dmq-node/src/DMQ/Tracer.hs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import Ouroboros.Network.ConnectionId
4646
import Ouroboros.Network.Diffusion qualified as Diffusion
4747
import Ouroboros.Network.Diffusion.Topology (NetworkTopology)
4848
import Ouroboros.Network.Driver (TraceSendRecv)
49+
import Ouroboros.Network.Magic (NetworkMagic (..))
4950
import Ouroboros.Network.OrphanInstances ()
5051
import Ouroboros.Network.PeerSelection.PublicRootPeers (PublicRootPeers)
5152
import Ouroboros.Network.PeerSelection.PublicRootPeers qualified as PublicRootPeers
@@ -67,12 +68,14 @@ import Cardano.Logging qualified as Logging
6768
import Cardano.Logging.Prometheus.TCPServer qualified as Logging
6869

6970
import DMQ.Configuration
71+
import DMQ.Diffusion.NodeKernel.Types (ValidationCfg)
7072
import DMQ.NodeToClient.LocalMsgNotification qualified as LMN
7173
import DMQ.NodeToClient.LocalMsgSubmission (TraceLocalMsgSubmission)
7274
import DMQ.NodeToClient.LocalStateQueryClient.Types
7375
(TraceLocalStateQueryClient (..))
7476
import DMQ.NodeToClient.Version as NtC
7577
import DMQ.NodeToNode.Version as NtN
78+
import DMQ.Policy qualified as Policy
7679
import DMQ.Protocol.LocalMsgNotification.Type (LocalMsgNotification)
7780
import DMQ.Protocol.LocalMsgNotification.Type qualified as LMN
7881
import DMQ.Protocol.LocalMsgSubmission.Type (LocalMsgSubmission,
@@ -132,6 +135,7 @@ data DMQStartupTrace
132135
| DMQTopology (NetworkTopology NoExtraConfig Diffusion.NoExtraFlags)
133136
| DMQTopologyError Text
134137
| DMQPrometheus Logging.TracePrometheusSimple
138+
| DMQValidationCfgWarning NetworkMagic ValidationCfg
135139

136140

137141
instance Logging.LogFormatting DMQStartupTrace where
@@ -157,6 +161,11 @@ instance Logging.LogFormatting DMQStartupTrace where
157161
, "error" .= e
158162
]
159163
forMachine dtal (DMQPrometheus msg) = Logging.forMachine dtal msg
164+
forMachine _dtal (DMQValidationCfgWarning magic cfg) =
165+
mconcat [ "kind" .= String "NonStandardValidationCfg"
166+
, "networkMagic" .= unNetworkMagic magic
167+
, "cfg" .= cfg
168+
]
160169

161170
instance Logging.MetaTrace DMQStartupTrace where
162171
namespaceFor DMQConfiguration{} = Logging.Namespace [] ["Configuration"]
@@ -165,9 +174,15 @@ instance Logging.MetaTrace DMQStartupTrace where
165174
namespaceFor DMQTopology{} = Logging.Namespace [] ["Topology"]
166175
namespaceFor DMQTopologyError{} = Logging.Namespace [] ["Topology", "Error"]
167176
namespaceFor DMQPrometheus {} = Logging.Namespace [] ["Prometheus"]
177+
namespaceFor DMQValidationCfgWarning {} = Logging.Namespace [] ["ValidationCfg"]
168178
severityFor _ (Just DMQConfigurationError{}) = Just Logging.Critical
169179
severityFor _ (Just DMQCardanoNodeSocketError{}) = Just Logging.Critical
170180
severityFor _ (Just DMQTopologyError{}) = Just Logging.Critical
181+
severityFor _ (Just (DMQValidationCfgWarning magic _))
182+
| magic == Policy.dmqMainnetNetworkMagic
183+
= Just Logging.Critical
184+
| otherwise
185+
= Just Logging.Warning
171186
severityFor _ _ = Just Logging.Info
172187
documentFor _ = Nothing
173188
allNamespaces =

0 commit comments

Comments
 (0)