Skip to content

Commit d078a1c

Browse files
peer-selection: verify peer snapshot with hash
1 parent 24e866a commit d078a1c

File tree

7 files changed

+86
-79
lines changed

7 files changed

+86
-79
lines changed

cardano-diffusion/cardano-diffusion.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ library
151151
aeson,
152152
base >=4.14 && <4.22,
153153
bytestring,
154+
cardano-crypto-class,
154155
cardano-diffusion:{api, protocols},
155156
containers,
156157
contra-tracer,

cardano-diffusion/lib/Cardano/Network/LedgerPeerConsensusInterface.hs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
{-# LANGUAGE RankNTypes #-}
2+
13
module Cardano.Network.LedgerPeerConsensusInterface
24
( LedgerPeersConsensusInterface (..)
35
-- * Re-exports
@@ -8,11 +10,14 @@ module Cardano.Network.LedgerPeerConsensusInterface
810

911
import Control.Concurrent.Class.MonadSTM (MonadSTM (..))
1012

11-
import Ouroboros.Network.BlockFetch.ConsensusInterface (FetchMode (..))
12-
13+
import Cardano.Crypto.Hash (Hash, Blake2b_256)
1314
import Cardano.Network.LedgerStateJudgement
1415
import Cardano.Network.PeerSelection.LocalRootPeers
1516
(OutboundConnectionsState (..))
17+
import Ouroboros.Network.BlockFetch.ConsensusInterface (FetchMode (..))
18+
import Ouroboros.Network.Block (SlotNo)
19+
import Ouroboros.Network.Point (Block)
20+
1621

1722
-- | Cardano Node specific consensus interface actions.
1823
--
@@ -31,4 +36,6 @@ data LedgerPeersConsensusInterface m =
3136
-- it only has local peers.
3237
--
3338
, updateOutboundConnectionsState :: OutboundConnectionsState -> STM m ()
39+
40+
, getBlockHash :: forall a. SlotNo -> STM m (Block SlotNo (Hash Blake2b_256 a))
3441
}

cardano-diffusion/lib/Cardano/Network/PeerSelection/Governor/Monitor.hs

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
{-# LANGUAGE LambdaCase #-}
2-
{-# LANGUAGE NamedFieldPuns #-}
3-
{-# LANGUAGE ScopedTypeVariables #-}
1+
{-# LANGUAGE DataKinds #-}
2+
{-# LANGUAGE DisambiguateRecordFields #-}
3+
{-# LANGUAGE GADTs #-}
4+
{-# LANGUAGE LambdaCase #-}
5+
{-# LANGUAGE NamedFieldPuns #-}
6+
{-# LANGUAGE PatternSynonyms #-}
7+
{-# LANGUAGE ScopedTypeVariables #-}
48

59
-- | This module contains governor decisions for monitoring tasks:
610
--
@@ -18,14 +22,18 @@ module Cardano.Network.PeerSelection.Governor.Monitor
1822
, ExtraTrace (..)
1923
) where
2024

21-
import Data.Set qualified as Set
22-
25+
import Control.Concurrent.JobPool (Job (..))
26+
import Control.Exception (assert)
2327
import Control.Monad.Class.MonadSTM
2428
import Control.Monad.Class.MonadTime.SI
2529
import Control.Monad.Class.MonadTimer.SI
30+
import Data.Map.Strict (Map)
31+
import Data.Map.Strict qualified as Map
32+
import Data.Set (Set)
33+
import Data.Set qualified as Set
2634

35+
import Cardano.Crypto.Hash as Crypto (castHash)
2736
import Cardano.Network.ConsensusMode
28-
import Cardano.Network.Diffusion.Configuration qualified as Cardano (srvPrefix)
2937
import Cardano.Network.LedgerPeerConsensusInterface qualified as Cardano
3038
import Cardano.Network.LedgerStateJudgement
3139
import Cardano.Network.PeerSelection.Bootstrap (UseBootstrapPeers (..),
@@ -37,24 +45,20 @@ import Cardano.Network.PeerSelection.Governor.PeerSelectionState qualified as Ca
3745
import Cardano.Network.PeerSelection.PeerTrustable (PeerTrustable (..))
3846
import Cardano.Network.PeerSelection.PublicRootPeers qualified as Cardano.PublicRootPeers
3947
import Cardano.Network.PeerSelection.State.LocalRootPeers qualified as LocalRootPeers
40-
import Control.Exception (assert)
41-
import Data.Map.Strict (Map)
42-
import Data.Map.Strict qualified as Map
43-
import Data.Set (Set)
48+
import Ouroboros.Network.Block (HeaderHash, pattern BlockPoint, SlotNo, atSlot, withHash)
4449
import Ouroboros.Network.PeerSelection.Governor.ActivePeers
4550
(jobDemoteActivePeer)
46-
import Ouroboros.Network.PeerSelection.Governor.Monitor (jobVerifyPeerSnapshot)
4751
import Ouroboros.Network.PeerSelection.Governor.Types hiding
4852
(PeerSelectionCounters)
4953
import Ouroboros.Network.PeerSelection.LedgerPeers.Type
50-
(LedgerPeersConsensusInterface (..))
54+
(LedgerPeersConsensusInterface (..), LedgerPeerSnapshot (..), LedgerPeersKind (..))
5155
import Ouroboros.Network.PeerSelection.PublicRootPeers qualified as PublicRootPeers
5256
import Ouroboros.Network.PeerSelection.State.EstablishedPeers qualified as EstablishedPeers
5357
import Ouroboros.Network.PeerSelection.State.KnownPeers qualified as KnownPeers
5458
import Ouroboros.Network.PeerSelection.State.LocalRootPeers
5559
(LocalRootConfig (..))
5660
import Ouroboros.Network.PeerSelection.Types
57-
import Ouroboros.Network.Point (Block (..), WithOrigin (..))
61+
import Ouroboros.Network.Point (Block (..))
5862

5963

6064
-- | Used to set 'bootstrapPeersTimeout' for crashing the node in a critical
@@ -496,8 +500,8 @@ monitorLedgerStateJudgement
496500
(TimedDecision m Cardano.ExtraState extraDebugState extraFlags
497501
(Cardano.ExtraPeers peeraddr) ExtraTrace peeraddr peerconn)
498502
monitorLedgerStateJudgement PeerSelectionActions{
499-
getLedgerStateCtx = ledgerCtx@LedgerPeersConsensusInterface {
500-
lpExtraAPI = Cardano.LedgerPeersConsensusInterface {
503+
getLedgerStateCtx = LedgerPeersConsensusInterface {
504+
lpExtraAPI = lpExtraAPI@Cardano.LedgerPeersConsensusInterface {
501505
Cardano.getLedgerStateJudgement = readLedgerStateJudgement
502506
}
503507
}
@@ -524,8 +528,9 @@ monitorLedgerStateJudgement PeerSelectionActions{
524528
Decision {
525529
decisionTrace = [ExtraTrace (TraceLedgerStateJudgementChanged lsj)],
526530
decisionJobs = case (lsj, ledgerPeerSnapshot) of
527-
(TooOld, Just ledgerPeerSnapshot') ->
528-
[jobVerifyPeerSnapshot Cardano.srvPrefix ledgerPeerSnapshot' ledgerCtx]
531+
(TooOld, Just (LedgerBigPeerSnapshotV23 point _magic _pools))
532+
| BlockPoint { atSlot, withHash } <- point ->
533+
[jobVerifyPeerSnapshot (atSlot, withHash) lpExtraAPI]
529534
_otherwise -> [],
530535
decisionState = st {
531536
extraState = cpst {
@@ -676,6 +681,35 @@ waitForSystemToQuiesce st@PeerSelectionState{
676681
| otherwise = GuardedSkip Nothing
677682

678683

684+
-- |This job, which is initiated by monitorLedgerStateJudgement job,
685+
-- verifies whether the provided big ledger pools match up with the
686+
-- ledger state once the node catches up to the slot at which the
687+
-- snapshot was ostensibly taken
688+
--
689+
jobVerifyPeerSnapshot :: (MonadSTM m)
690+
=> (SlotNo, HeaderHash (LedgerPeerSnapshot BigLedgerPeers))
691+
-> Cardano.LedgerPeersConsensusInterface m
692+
-> Job () m (Completion m extraState extraDebugState extraFlags extraPeers extraTrace peeraddr peerconn)
693+
jobVerifyPeerSnapshot (slotNo, theHash)
694+
Cardano.LedgerPeersConsensusInterface { getBlockHash }
695+
= Job job (const (completion False)) () "jobVerifyPeerSnapshot"
696+
where
697+
completion result = return . Completion $ \st _now ->
698+
Decision {
699+
decisionTrace = [TraceVerifyPeerSnapshot result],
700+
decisionState = st,
701+
decisionJobs = [] }
702+
703+
job = do
704+
Block { blockPointHash } <- atomically $ getBlockHash slotNo
705+
let result = theHash == Crypto.castHash blockPointHash
706+
return . Completion $ \st _now ->
707+
Decision {
708+
decisionTrace = [TraceVerifyPeerSnapshot result],
709+
decisionState = st,
710+
decisionJobs = [] }
711+
712+
679713
-- | Extra trace points for `TracePeerSelection`.
680714
--
681715
-- TODO: it ought to be moved to `Types`, but that introduces a circular

ouroboros-network/lib/Ouroboros/Network/Diffusion/Types.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ data Configuration extraFlags m ntnFd ntnAddr ntcFd ntcAddr = Configuration {
473473
-- These peers may be selected by ledgerPeersThread when requested
474474
-- by the peer selection governor when the node is syncing up.
475475
-- This is especially useful for Genesis consensus mode.
476-
, dcReadLedgerPeerSnapshot :: STM m (Maybe LedgerPeerSnapshot)
476+
, dcReadLedgerPeerSnapshot :: STM m (Maybe (LedgerPeerSnapshot BigLedgerPeers))
477477

478478
-- | `UseLedgerPeers` from topology file.
479479
--

ouroboros-network/lib/Ouroboros/Network/PeerSelection/Governor/Monitor.hs

Lines changed: 6 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE GADTs #-}
12
{-# LANGUAGE NamedFieldPuns #-}
23
{-# LANGUAGE ScopedTypeVariables #-}
34

@@ -11,7 +12,6 @@
1112
module Ouroboros.Network.PeerSelection.Governor.Monitor
1213
( targetPeers
1314
, jobs
14-
, jobVerifyPeerSnapshot
1515
, connections
1616
, localRoots
1717
, ledgerPeerSnapshotChange
@@ -23,27 +23,21 @@ import Data.Maybe (fromMaybe, isJust)
2323
import Data.Set (Set)
2424
import Data.Set qualified as Set
2525

26-
import Control.Concurrent.JobPool (Job (..), JobPool)
26+
import Control.Concurrent.JobPool (JobPool)
2727
import Control.Concurrent.JobPool qualified as JobPool
2828
import Control.Exception (assert)
2929
import Control.Monad.Class.MonadSTM
3030
import Control.Monad.Class.MonadTime.SI
3131
import Control.Monad.Class.MonadTimer.SI
3232
import System.Random (randomR)
3333

34-
import Ouroboros.Network.Block (HeaderHash, SlotNo)
3534
import Ouroboros.Network.ExitPolicy (RepromoteDelay)
3635
import Ouroboros.Network.ExitPolicy qualified as ExitPolicy
3736
import Ouroboros.Network.PeerSelection.Governor.ActivePeers
3837
(jobDemoteActivePeer)
3938
import Ouroboros.Network.PeerSelection.Governor.Types hiding
4039
(PeerSelectionCounters)
41-
import Ouroboros.Network.PeerSelection.LedgerPeers.Type
42-
(LedgerPeerSnapshot (..), LedgerPeersConsensusInterface (..),
43-
SRVPrefix, compareLedgerPeerSnapshotApproximate,
44-
getRelayAccessPointsFromLedger,
45-
getRelayAccessPointsFromLedgerPeerSnapshot)
46-
import Ouroboros.Network.PeerSelection.LedgerPeers.Utils
40+
import Ouroboros.Network.PeerSelection.LedgerPeers.Type (LedgerPeerSnapshot (..))
4741
import Ouroboros.Network.PeerSelection.PublicRootPeers qualified as PublicRootPeers
4842
import Ouroboros.Network.PeerSelection.State.EstablishedPeers qualified as EstablishedPeers
4943
import Ouroboros.Network.PeerSelection.State.KnownPeers qualified as KnownPeers
@@ -410,38 +404,6 @@ localRoots actions@PeerSelectionActions{ readLocalRootPeers
410404
| (peeraddr, peerconn) <- Map.assocs selectedToDemote' ]
411405
}
412406

413-
-- |This job, which is initiated by monitorLedgerStateJudgement job,
414-
-- verifies whether the provided big ledger pools match up with the
415-
-- ledger state once the node catches up to the slot at which the
416-
-- snapshot was ostensibly taken
417-
--
418-
jobVerifyPeerSnapshot :: MonadSTM m
419-
=> SRVPrefix
420-
-> LedgerPeerSnapshot
421-
-> LedgerPeersConsensusInterface extraAPI m
422-
-> Job () m (Completion m extraState extraDebugState extraFlags extraPeers extraTrace peeraddr peerconn)
423-
jobVerifyPeerSnapshot srvPrefix
424-
ledgerPeerSnapshot
425-
ledgerCtx@LedgerPeersConsensusInterface { lpGetLatestSlot }
426-
= Job job (const (completion False)) () "jobVerifyPeerSnapshot"
427-
where
428-
(slot, snapshotPeers) =
429-
getRelayAccessPointsFromLedgerPeerSnapshot srvPrefix ledgerPeerSnapshot
430-
431-
completion result = return . Completion $ \st _now ->
432-
Decision {
433-
decisionTrace = [TraceVerifyPeerSnapshot result],
434-
decisionState = st,
435-
decisionJobs = [] }
436-
437-
job = do
438-
ledgerPeers <-
439-
atomically $ do
440-
check . (>= slot) =<< lpGetLatestSlot
441-
accumulateBigLedgerStake <$> getRelayAccessPointsFromLedger srvPrefix ledgerCtx
442-
completion $ snapshotPeers
443-
`compareLedgerPeerSnapshotApproximate`
444-
ledgerPeers
445407

446408
-- |This job monitors for any changes in the big ledger peer snapshot
447409
-- and flips ledger state judgement private state so that monitoring action
@@ -464,8 +426,9 @@ ledgerPeerSnapshotChange extraStateChange
464426
ledgerPeerSnapshot' <- readLedgerPeerSnapshot
465427
case (ledgerPeerSnapshot', ledgerPeerSnapshot) of
466428
(Nothing, _) -> retry
467-
(Just (LedgerPeerSnapshot (slot, _)), Just (LedgerPeerSnapshot (slot', _)))
468-
| slot == slot' -> retry
429+
(Just (LedgerBigPeerSnapshotV23 point _magic _pools),
430+
Just (LedgerBigPeerSnapshotV23 point' _magic' _pools'))
431+
| point == point' -> retry
469432
_otherwise ->
470433
return $ \_now ->
471434
Decision { decisionTrace = [],

ouroboros-network/lib/Ouroboros/Network/PeerSelection/Governor/Types.hs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{-# LANGUAGE BangPatterns #-}
22
{-# LANGUAGE CPP #-}
3+
{-# LANGUAGE DataKinds #-}
34
{-# LANGUAGE DeriveFunctor #-}
45
{-# LANGUAGE ExistentialQuantification #-}
56
{-# LANGUAGE FlexibleContexts #-}
@@ -9,6 +10,7 @@
910
{-# LANGUAGE RecordWildCards #-}
1011
{-# LANGUAGE ScopedTypeVariables #-}
1112
{-# LANGUAGE StandaloneDeriving #-}
13+
{-# LANGUAGE UndecidableInstances #-}
1214
{-# LANGUAGE ViewPatterns #-}
1315

1416
#if __GLASGOW_HASKELL__ < 904
@@ -70,6 +72,11 @@ module Ouroboros.Network.PeerSelection.Governor.Types
7072
, DemotionTimeoutException (..)
7173
) where
7274

75+
import Control.Applicative (Alternative)
76+
import Control.Concurrent.Class.MonadSTM.Strict
77+
import Control.Concurrent.JobPool (Job)
78+
import Control.Exception (Exception (..), SomeException, assert)
79+
import Control.Monad.Class.MonadTime.SI
7380
import Data.Map.Strict (Map)
7481
import Data.Map.Strict qualified as Map
7582
import Data.Maybe (fromMaybe)
@@ -81,12 +88,6 @@ import Data.Set qualified as Set
8188
import GHC.Stack (HasCallStack)
8289
import System.Random (StdGen)
8390

84-
import Control.Applicative (Alternative)
85-
import Control.Concurrent.Class.MonadSTM.Strict
86-
import Control.Concurrent.JobPool (Job)
87-
import Control.Exception (Exception (..), SomeException, assert)
88-
import Control.Monad.Class.MonadTime.SI
89-
9091
import Ouroboros.Network.DiffusionMode
9192
import Ouroboros.Network.ExitPolicy
9293
import Ouroboros.Network.PeerSelection.LedgerPeers.Type
@@ -351,7 +352,7 @@ data PeerSelectionActions extraState extraFlags extraPeers extraAPI extraCounter
351352

352353
-- | Read the current state of ledger peer snapshot
353354
--
354-
readLedgerPeerSnapshot :: STM m (Maybe LedgerPeerSnapshot)
355+
readLedgerPeerSnapshot :: STM m (Maybe (LedgerPeerSnapshot BigLedgerPeers))
355356
}
356357

357358
-- | Interfaces required by the peer selection governor, which do not need to
@@ -646,7 +647,7 @@ data PeerSelectionState extraState extraFlags extraPeers peeraddr peerconn =
646647

647648
-- | Internal state of ledger peer snapshot
648649
--
649-
ledgerPeerSnapshot :: Maybe LedgerPeerSnapshot,
650+
ledgerPeerSnapshot :: Maybe (LedgerPeerSnapshot BigLedgerPeers),
650651

651652
-- | Extension point so that 3rd party users can plug their own peer
652653
-- selection state if needed

ouroboros-network/lib/Ouroboros/Network/PeerSelection/LedgerPeers.hs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{-# LANGUAGE BangPatterns #-}
22
{-# LANGUAGE CPP #-}
3+
{-# LANGUAGE DataKinds #-}
34
{-# LANGUAGE DerivingStrategies #-}
45
{-# LANGUAGE GADTs #-}
56
{-# LANGUAGE LambdaCase #-}
@@ -36,10 +37,12 @@ module Ouroboros.Network.PeerSelection.LedgerPeers
3637
, resolveLedgerPeers
3738
) where
3839

40+
import Control.Concurrent.Class.MonadSTM.Strict
3941
import Control.Monad (when)
4042
import Control.Monad.Class.MonadAsync
4143
import Control.Monad.Class.MonadFork
4244
import Control.Monad.Class.MonadTime.SI
45+
import Control.Monad.Class.MonadThrow
4346
import Control.Tracer (Tracer, traceWith)
4447
import Data.IP qualified as IP
4548
import Data.List as List (foldl')
@@ -49,16 +52,14 @@ import Data.Map.Strict (Map)
4952
import Data.Map.Strict qualified as Map
5053
import Data.Maybe (isJust)
5154
import Data.Ratio
52-
import System.Random
53-
import Text.Printf
54-
55-
import Control.Concurrent.Class.MonadSTM.Strict
56-
import Control.Monad.Class.MonadThrow
5755
import Data.Set (Set)
5856
import Data.Set qualified as Set
5957
import Data.Void (Void)
6058
import Data.Word (Word16, Word64)
6159
import Network.DNS qualified as DNS
60+
import System.Random
61+
import Text.Printf
62+
6263
import Ouroboros.Network.Block (SlotNo)
6364
import Ouroboros.Network.PeerSelection.LedgerPeers.Type
6465
import Ouroboros.Network.PeerSelection.LedgerPeers.Utils
@@ -381,7 +382,7 @@ ledgerPeersThread PeerActionsDNS {
381382
data StakeMapOverSource = StakeMapOverSource {
382383
ledgerWithOrigin :: WithOrigin SlotNo,
383384
ledgerPeers :: LedgerPeers,
384-
peerSnapshot :: Maybe LedgerPeerSnapshot,
385+
peerSnapshot :: Maybe (LedgerPeerSnapshot BigLedgerPeers),
385386
cachedSlot :: Maybe SlotNo,
386387
peerMap :: Map AccPoolStake (PoolStake, NonEmpty RelayAccessPoint),
387388
bigPeerMap :: Map AccPoolStake (PoolStake, NonEmpty RelayAccessPoint),
@@ -412,7 +413,7 @@ stakeMapWithSlotOverSource StakeMapOverSource {
412413
-- check if we can use the snapshot first
413414
(ledgerSlotNo, _, Just ledgerPeerSnapshot)
414415
| (At snapshotSlotNo, snapshotRelays)
415-
<- getRelayAccessPointsFromLedgerPeerSnapshot srvPrefix ledgerPeerSnapshot
416+
<- getRelayAccessPointsFromBigLedgerPeersSnapshot srvPrefix ledgerPeerSnapshot
416417
, snapshotSlotNo >= ledgerSlotNo'
417418
, snapshotSlotNo >= useLedgerAfter' ->
418419
-- we cache the peers from the snapshot
@@ -448,7 +449,7 @@ data WithLedgerPeersArgs extraAPI m = WithLedgerPeersArgs {
448449
-- ^ Get Ledger Peers comes from here
449450
wlpGetUseLedgerPeers :: STM m UseLedgerPeers,
450451
-- ^ Get Use Ledger After value
451-
wlpGetLedgerPeerSnapshot :: STM m (Maybe LedgerPeerSnapshot),
452+
wlpGetLedgerPeerSnapshot :: STM m (Maybe (LedgerPeerSnapshot BigLedgerPeers)),
452453
-- ^ Get ledger peer snapshot from file read by node
453454
wlpSemaphore :: DNSSemaphore m,
454455
wlpSRVPrefix :: SRVPrefix

0 commit comments

Comments
 (0)