@@ -99,6 +99,8 @@ data LeiosNodeState m = LeiosNodeState
9999 , relayIBState :: ! (RelayIBState m )
100100 , relayEBState :: ! (RelayEBState m )
101101 , relayVoteState :: ! (RelayVoteState m )
102+ , prunedVoteStateToVar :: ! (TVar m SlotNo )
103+ -- ^ TODO: refactor into RelayState.
102104 , ibDeliveryTimesVar :: ! (TVar m (Map InputBlockId UTCTime ))
103105 , taskQueue :: ! (TaskMultiQueue LeiosNodeTask m )
104106 , waitingForRBVar :: ! (TVar m (Map (HeaderHash RankingBlock ) [STM m () ]))
@@ -107,6 +109,8 @@ data LeiosNodeState m = LeiosNodeState
107109 -- ^ waiting for ledger state of RB block to be validated.
108110 , ledgerStateVar :: ! (TVar m (Map (HeaderHash RankingBlock ) LedgerState ))
109111 , ibsNeededForEBVar :: ! (TVar m (Map EndorseBlockId (Set InputBlockId )))
112+ , votesForEBVar :: ! (TVar m (Map EndorseBlockId (Map VoteId Word64 )))
113+ -- ^ TODO: prune of EBs that won't make it into chain anymore.
110114 }
111115
112116data LeiosNodeTask
@@ -220,8 +224,9 @@ relayIBConfig ::
220224 LeiosNodeConfig ->
221225 ([InputBlockHeader ] -> m () ) ->
222226 SubmitBlocks m InputBlockHeader InputBlockBody ->
227+ RelayIBState m ->
223228 RelayConsumerConfig InputBlockId InputBlockHeader InputBlockBody m
224- relayIBConfig _tracer cfg validateHeaders submitBlocks =
229+ relayIBConfig _tracer cfg validateHeaders submitBlocks st =
225230 RelayConsumerConfig
226231 { relay = RelayConfig {maxWindowSize = coerce cfg. leios. ibDiffusion. maxWindowSize}
227232 , headerId = (. id )
@@ -231,15 +236,19 @@ relayIBConfig _tracer cfg validateHeaders submitBlocks =
231236 , maxHeadersToRequest = cfg. leios. ibDiffusion. maxHeadersToRequest
232237 , maxBodiesToRequest = cfg. leios. ibDiffusion. maxBodiesToRequest
233238 , submitBlocks
239+ , shouldIgnore = do
240+ buff <- readTVarIO st. relayBufferVar
241+ return $ flip RB. member buff . (. id )
234242 }
235243
236244relayEBConfig ::
237- MonadDelay m =>
245+ ( MonadDelay m , MonadSTM m ) =>
238246 Tracer m LeiosNodeEvent ->
239247 LeiosNodeConfig ->
240248 SubmitBlocks m EndorseBlockId EndorseBlock ->
249+ RelayEBState m ->
241250 RelayConsumerConfig EndorseBlockId (RelayHeader EndorseBlockId ) EndorseBlock m
242- relayEBConfig _tracer cfg submitBlocks =
251+ relayEBConfig _tracer cfg submitBlocks st =
243252 RelayConsumerConfig
244253 { relay = RelayConfig {maxWindowSize = coerce cfg. leios. ebDiffusion. maxWindowSize}
245254 , headerId = (. id )
@@ -250,15 +259,20 @@ relayEBConfig _tracer cfg submitBlocks =
250259 , maxBodiesToRequest = cfg. leios. ebDiffusion. maxBodiesToRequest
251260 , submitBlocks = \ hbs t k ->
252261 submitBlocks (map (first (. id )) hbs) t (k . map (\ (i, b) -> (RelayHeader i b. slot, b)))
262+ , shouldIgnore = do
263+ buff <- readTVarIO st. relayBufferVar
264+ return $ flip RB. member buff . (. id )
253265 }
254266
255267relayVoteConfig ::
256- MonadDelay m =>
268+ ( MonadDelay m , Monad ( STM m ), MonadSTM m , MonadTime m ) =>
257269 Tracer m LeiosNodeEvent ->
258270 LeiosNodeConfig ->
259271 SubmitBlocks m VoteId VoteMsg ->
272+ RelayVoteState m ->
273+ LeiosNodeState m ->
260274 RelayConsumerConfig VoteId (RelayHeader VoteId ) VoteMsg m
261- relayVoteConfig _tracer cfg submitBlocks =
275+ relayVoteConfig _tracer cfg submitBlocks _ leiosState =
262276 RelayConsumerConfig
263277 { relay = RelayConfig {maxWindowSize = coerce cfg. leios. voteDiffusion. maxWindowSize}
264278 , headerId = (. id )
@@ -269,6 +283,12 @@ relayVoteConfig _tracer cfg submitBlocks =
269283 , maxBodiesToRequest = cfg. leios. voteDiffusion. maxBodiesToRequest
270284 , submitBlocks = \ hbs t k ->
271285 submitBlocks (map (first (. id )) hbs) t (k . map (\ (i, b) -> (RelayHeader i b. slot, b)))
286+ , shouldIgnore = atomically $ do
287+ buffer <- readTVar leiosState. relayVoteState. relayBufferVar
288+ prunedTo <- readTVar leiosState. prunedVoteStateToVar
289+ return $ \ hd ->
290+ hd. slot < prunedTo
291+ || hd. id `RB.member` buffer
272292 }
273293
274294queueAndWait :: (MonadSTM m , MonadDelay m ) => LeiosNodeState m -> LeiosNodeTask -> [CPUTask ] -> m ()
@@ -298,6 +318,8 @@ newLeiosNodeState cfg = do
298318 waitingForRBVar <- newTVarIO Map. empty
299319 waitingForLedgerStateVar <- newTVarIO Map. empty
300320 taskQueue <- atomically $ newTaskMultiQueue cfg. processingQueueBound
321+ prunedVoteStateToVar <- newTVarIO (toEnum 0 )
322+ votesForEBVar <- newTVarIO Map. empty
301323 return $ LeiosNodeState {.. }
302324
303325leiosNode ::
@@ -352,21 +374,21 @@ leiosNode tracer cfg followers peers = do
352374
353375 ibThreads <-
354376 setupRelay
355- (relayIBConfig tracer cfg valHeaderIB submitIB)
377+ (relayIBConfig tracer cfg valHeaderIB submitIB relayIBState )
356378 relayIBState
357379 (map (. protocolIB) followers)
358380 (map (. protocolIB) peers)
359381
360382 ebThreads <-
361383 setupRelay
362- (relayEBConfig tracer cfg submitEB)
384+ (relayEBConfig tracer cfg submitEB relayEBState )
363385 relayEBState
364386 (map (. protocolEB) followers)
365387 (map (. protocolEB) peers)
366388
367389 voteThreads <-
368390 setupRelay
369- (relayVoteConfig tracer cfg submitVote)
391+ (relayVoteConfig tracer cfg submitVote relayVoteState leiosState )
370392 relayVoteState
371393 (map (. protocolVote) followers)
372394 (map (. protocolVote) peers)
@@ -419,13 +441,15 @@ pruneVoteBuffer ::
419441pruneVoteBuffer _tracer cfg st = go (toEnum 0 )
420442 where
421443 go p = do
422- let last_vote_recv = snd $ stageRangeOf cfg. leios p VoteRecv
423444 let last_vote_send = snd $ stageRangeOf cfg. leios p VoteSend
445+ let last_vote_recv = snd $ stageRangeOf cfg. leios p VoteRecv
446+ let pruneTo = succ last_vote_send
424447 _ <- waitNextSlot cfg. slotConfig (succ last_vote_recv)
425448 atomically $ do
426449 modifyTVar' st. relayVoteState. relayBufferVar $
427450 RB. filter $
428- \ RB. EntryWithTicket {value} -> (snd value). slot <= last_vote_send
451+ \ RB. EntryWithTicket {value} -> (snd value). slot >= pruneTo
452+ writeTVar st. prunedVoteStateToVar $! pruneTo
429453 go (succ p)
430454
431455computeLedgerStateThread ::
@@ -479,6 +503,18 @@ adoptEB leiosState eb = do
479503 let ibsNeeded = Map. fromList [(eb. id , Set. fromList eb. inputBlocks Set. \\ ibs)]
480504 modifyTVar' leiosState. ibsNeededForEBVar (`Map.union` ibsNeeded)
481505
506+ adoptVote :: MonadSTM m => LeiosNodeState m -> VoteMsg -> STM m ()
507+ adoptVote leiosState v = do
508+ -- We keep tally for each EB as votes arrive, so the relayVoteBuffer
509+ -- can be pruned without effects on EB certification.
510+ modifyTVar' leiosState. votesForEBVar $
511+ Map. unionWith Map. union $
512+ Map. fromListWith
513+ Map. union
514+ [ (eb, Map. singleton v. id v. votes)
515+ | eb <- v. endorseBlocks
516+ ]
517+
482518dispatchValidation ::
483519 forall m .
484520 (MonadMVar m , MonadFork m , MonadAsync m , MonadSTM m , MonadTime m , MonadDelay m ) =>
@@ -509,7 +545,9 @@ dispatchValidation tracer cfg leiosState req =
509545 adoptEB leiosState eb
510546 traceEnterState [eb] EventEB
511547 valVote v completion = labelTask . (ValVote ,) . (\ p -> cpuTask p cfg. leios. delays. voteMsgValidation v,) $ do
512- atomically $ completion [v]
548+ atomically $ do
549+ completion [v]
550+ adoptVote leiosState v
513551 traceEnterState [v] EventVote
514552
515553 go :: ValidationRequest m -> STM m [(LeiosNodeTask , (CPUTask , m () ))]
@@ -589,7 +627,11 @@ generator tracer cfg st = do
589627 adoptEB st eb
590628 traceWith tracer (LeiosNodeEvent Generate (EventEB eb))
591629 SomeAction Generate. Vote v -> (GenVote ,) $ do
592- atomically $ modifyTVar' st. relayVoteState. relayBufferVar (RB. snoc v. id (RelayHeader v. id v. slot, v))
630+ atomically $ do
631+ modifyTVar'
632+ st. relayVoteState. relayBufferVar
633+ (RB. snoc v. id (RelayHeader v. id v. slot, v))
634+ adoptVote st v
593635 traceWith tracer (LeiosNodeEvent Generate (EventVote v))
594636 let LeiosNodeConfig {.. } = cfg
595637 leiosBlockGenerator $ LeiosGeneratorConfig {submit = mapM_ submitOne, .. }
@@ -602,8 +644,7 @@ mkBuffersView cfg st = BuffersView{..}
602644 -- though it's getting more expensive as we go.
603645 chain <- PraosNode. preferredChain st. praosState
604646 bufferEB <- readTVar st. relayEBState. relayBufferVar
605- bufferVotes <- map snd . RB. values <$> readTVar st. relayVoteState. relayBufferVar
606-
647+ votesForEB <- readTVar st. votesForEBVar
607648 -- RBs in the same chain should not contain certificates for the same pipeline.
608649 let pipelinesInChain =
609650 Set. fromList $
@@ -612,14 +653,6 @@ mkBuffersView cfg st = BuffersView{..}
612653 , (ebId, _) <- rb. blockBody. endorseBlocks
613654 , Just (_, eb) <- [RB. lookup bufferEB ebId]
614655 ]
615- -- TODO: cache?
616- let votesForEB =
617- Map. fromListWith
618- Map. union
619- [ (eb, Map. singleton v. id v. votes)
620- | v <- bufferVotes
621- , eb <- v. endorseBlocks
622- ]
623656 let totalVotes = fromIntegral . sum . Map. elems
624657 let tryCertify eb = do
625658 votes <- Map. lookup eb. id votesForEB
0 commit comments