Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ import LeiosVoteState
, LeiosVoteSubscription (..)
, subscribeVotes
)
import LeiosVoting (waitUntilCaughtUp)
import qualified Network.Mux as Mux
import Network.TypedProtocol.Codec
import Network.TypedProtocol.Peer (Peer (Effect))
Expand Down Expand Up @@ -501,6 +502,12 @@ mkHandlers
void $ MVar.tryPutMVar getLeiosReady ()
MsgLeiosVotes vs -> do
traceWith tracer $ MkTraceLeiosPeer $ "MsgLeiosVotes " <> show vs
-- Don't tally votes until the node has caught up
-- (see 'waitUntilCaughtUp'); otherwise a remote vote
-- could tip a certification while our own
-- selection/ledger is still far behind the round it
-- refers to.
atomically $ waitUntilCaughtUp getGsmState
forM_ vs $ \vote -> do
result <- addVote vote
traceWith kernelTracer TraceLeiosVoteAcquired{vote}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,7 @@ initNodeKernel
btime
leiosDB
leiosVoteState
(readTVar varGsmState)
(topLevelConfigVotingKey cfg)

return
Expand Down
26 changes: 24 additions & 2 deletions ouroboros-consensus/src/ouroboros-consensus/LeiosVoting.hs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import Ouroboros.Consensus.HeaderValidation
, headerStateTip
)
import Ouroboros.Consensus.Ledger.Extended (headerState, ledgerState)
import Ouroboros.Consensus.Node.GsmState (GsmState (..))
import Ouroboros.Consensus.Storage.ChainDB (ChainDB)
import qualified Ouroboros.Consensus.Storage.ChainDB as ChainDB
import Ouroboros.Consensus.Storage.LedgerDB.Forker
Expand Down Expand Up @@ -107,9 +108,15 @@ runLeiosVoting ::
BlockchainTime m ->
LeiosDbHandle m ->
LeiosVoteState m ->
-- | Current GSM state, so voting can stay paused until the node has
-- caught up. Before Genesis sync completes, the node's selected chain
-- and ledger state are far behind the real network, so committees
-- resolved from its own ledger and EB/RB points announced by peers
-- don't correspond to the round the rest of the network is voting on.
STM m GsmState ->
Maybe LeiosSigningKey ->
m ()
runLeiosVoting tracer chainDB btime leiosDB voteState = \case
runLeiosVoting tracer chainDB btime leiosDB voteState readGsmState = \case
Nothing ->
traceWith tracer $
MkTraceLeiosKernel
Expand Down Expand Up @@ -161,7 +168,8 @@ runLeiosVoting tracer chainDB btime leiosDB voteState = \case
-- so we can't stall a due vote behind a chan drain.
forever $ do
mWork <-
atomically $
atomically $ do
waitUntilCaughtUp readGsmState
(Just <$> takeReady) `orElse` (Nothing <$ takeAcquisition)
case mWork of
Nothing -> pure ()
Expand Down Expand Up @@ -191,6 +199,20 @@ runLeiosVoting tracer chainDB btime leiosDB voteState = \case
err ->
error $ "runLeiosVoting: unexpected error on addVote: " <> show err

-- | Block until the node has caught up ('GsmState' is 'CaughtUp').
--
-- Before that, our selection and ledger are stale relative to the round
-- the rest of the network is voting on, so committees resolved from our
-- own ledger, or certifications tallied from peers' votes, would be
-- computed against the wrong point. Meant to be composed into a larger
-- 'atomically' block and re-checked on every iteration of a loop (not
-- just once at startup), since GSM can fall back out of 'CaughtUp'.
waitUntilCaughtUp :: IOLike m => STM m GsmState -> STM m ()
waitUntilCaughtUp readGsmState =
readGsmState >>= \case
CaughtUp -> pure ()
_ -> retry

-- | Read the current wall-clock slot, retrying until it is known.
knownSlot :: IOLike m => BlockchainTime m -> STM m SlotNo
knownSlot btime =
Expand Down
Loading