@@ -13,6 +13,7 @@ module Ouroboros.Network.TxSubmission.Inbound.Registry
13
13
, newTxChannelsVar
14
14
, PeerTxAPI (.. )
15
15
, decisionLogicThread
16
+ , drainRejectionThread
16
17
, withPeer
17
18
) where
18
19
@@ -21,20 +22,22 @@ import Control.Concurrent.Class.MonadSTM.Strict
21
22
import Control.Monad.Class.MonadFork
22
23
import Control.Monad.Class.MonadThrow
23
24
import Control.Monad.Class.MonadTimer.SI
25
+ import Control.Monad.Class.MonadTime.SI
24
26
25
27
import Data.Foldable (traverse_
26
28
#if !MIN_VERSION_base(4,20,0)
27
29
, foldl'
28
30
#endif
29
31
)
30
- import Data.Typeable ( Typeable )
32
+ import Data.Hashable
31
33
import Data.Map.Strict (Map )
32
34
import Data.Map.Strict qualified as Map
33
35
import Data.Maybe (fromMaybe )
34
36
import Data.Sequence.Strict (StrictSeq )
35
37
import Data.Sequence.Strict qualified as StrictSeq
36
38
import Data.Set (Set )
37
39
import Data.Set qualified as Set
40
+ import Data.Typeable (Typeable )
38
41
import Data.Void (Void )
39
42
40
43
import Control.Tracer (Tracer , traceWith )
@@ -79,8 +82,11 @@ data PeerTxAPI m txid tx = PeerTxAPI {
79
82
-> m (Maybe TxSubmissionProtocolError ),
80
83
-- ^ handle received txs
81
84
82
- countRejectedTxs :: Int
83
- -> m Int ,
85
+ countRejectedTxs :: Time
86
+ -> Double
87
+ -> m Double ,
88
+ -- ^ updated score. The `Double` is difference between accepted and
89
+ -- rejected transactions.
84
90
85
91
consumeFetchedTxs :: Set txid
86
92
-> m (Set txid )
@@ -166,6 +172,7 @@ withPeer tracer
166
172
unacknowledgedTxIds = StrictSeq. empty,
167
173
unknownTxs = Set. empty,
168
174
rejectedTxs = 0 ,
175
+ rejectedTxsTs = Time 0 ,
169
176
fetchedTxs = Set. empty }
170
177
peerTxStates
171
178
}
@@ -238,9 +245,11 @@ withPeer tracer
238
245
peeraddr peerTxStates
239
246
in st {peerTxStates = peerTxStates' }
240
247
241
- countRejectedTxs :: Int
242
- -> m Int
243
- countRejectedTxs n = atomically $ do
248
+
249
+ countRejectedTxs :: Time
250
+ -> Double
251
+ -> m Double
252
+ countRejectedTxs now n = atomically $ do
244
253
modifyTVar sharedStateVar cntRejects
245
254
st <- readTVar sharedStateVar
246
255
case Map. lookup peeraddr (peerTxStates st) of
@@ -251,10 +260,10 @@ withPeer tracer
251
260
-> SharedTxState peeraddr txid tx
252
261
cntRejects st@ SharedTxState { peerTxStates } =
253
262
let peerTxStates' =
254
- Map. update
255
- ( \ ps -> Just $! ps { rejectedTxs = min 42 ( max ( - 42 ) (rejectedTxs ps + n)) })
256
- peeraddr peerTxStates
257
- in st { peerTxStates = peerTxStates' }
263
+ Map. update ( \ ps -> Just $! (updateRejects now n ps))
264
+ peeraddr peerTxStates
265
+ in st {peerTxStates = peerTxStates'}
266
+
258
267
259
268
consumeFetchedTxs :: Set txid
260
269
-> m (Set txid )
@@ -274,6 +283,48 @@ withPeer tracer
274
283
return o
275
284
276
285
286
+ updateRejects
287
+ :: Time
288
+ -> Double
289
+ -> PeerTxState txid tx
290
+ -> PeerTxState txid tx
291
+ updateRejects now 0 pts | rejectedTxs pts == 0
292
+ = pts {rejectedTxsTs = now}
293
+ updateRejects now n pts@ PeerTxState { rejectedTxs, rejectedTxsTs } =
294
+ let duration = diffTime now rejectedTxsTs
295
+ rate = 0.1 -- 0.1 rejected tx/s
296
+ maxTokens = 15 * 60 * rate -- 15 minutes worth of rejections
297
+ ! drain = realToFrac duration * rate
298
+ ! drained = max 0 $ rejectedTxs - drain in
299
+ pts { rejectedTxs = max 0 $ min maxTokens $ drained + n
300
+ , rejectedTxsTs = now }
301
+
302
+
303
+ drainRejectionThread
304
+ :: forall m peeraddr txid tx .
305
+ ( MonadDelay m
306
+ , MonadSTM m
307
+ , MonadThread m
308
+ )
309
+ => SharedTxStateVar m peeraddr txid tx
310
+ -> m Void
311
+ drainRejectionThread sharedStateVar = do
312
+ labelThisThread " tx-rejection-drain"
313
+ go
314
+ where
315
+ go :: m Void
316
+ go = do
317
+ threadDelay 7
318
+
319
+ ! now <- getMonotonicTime
320
+ atomically $ do
321
+ st <- readTVar sharedStateVar
322
+ let ptss = Map. map (\ pts -> updateRejects now 0 pts) (peerTxStates st)
323
+ writeTVar sharedStateVar (st { peerTxStates = ptss })
324
+
325
+ go
326
+
327
+
277
328
decisionLogicThread
278
329
:: forall m peeraddr txid tx .
279
330
( MonadDelay m
@@ -283,6 +334,7 @@ decisionLogicThread
283
334
, MonadFork m
284
335
, Ord peeraddr
285
336
, Ord txid
337
+ , Hashable peeraddr
286
338
)
287
339
=> Tracer m (TraceTxLogic peeraddr txid tx )
288
340
-> TxDecisionPolicy
0 commit comments