Skip to content

Commit

Permalink
LedgerSupportsPeerSelection: return peers registered in ledger state
Browse files Browse the repository at this point in the history
Fixes #2535.
  • Loading branch information
mrBliss committed Nov 11, 2020
1 parent da2130c commit c8fb01c
Show file tree
Hide file tree
Showing 17 changed files with 186 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ import Ouroboros.Consensus.Ledger.Abstract
import Ouroboros.Consensus.Ledger.CommonProtocolParams
import Ouroboros.Consensus.Ledger.Extended
import Ouroboros.Consensus.Ledger.Query
import Ouroboros.Consensus.Ledger.SupportsPeerSelection
import Ouroboros.Consensus.Ledger.SupportsProtocol
import Ouroboros.Consensus.Protocol.PBFT
import Ouroboros.Consensus.Util (ShowProxy (..))
Expand Down Expand Up @@ -212,6 +213,9 @@ instance ShowQuery (Query ByronBlock) where

instance ShowProxy (Query ByronBlock) where

instance LedgerSupportsPeerSelection ByronBlock where
getPeers = const []

instance CommonProtocolParams ByronBlock where
maxHeaderSize = fromIntegral . Update.ppMaxHeaderSize . getProtocolParameters
maxTxSize = fromIntegral . Update.ppMaxTxSize . getProtocolParameters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ import Ouroboros.Consensus.Ledger.Extended
import Ouroboros.Consensus.Ledger.Inspect
import Ouroboros.Consensus.Ledger.Query
import Ouroboros.Consensus.Ledger.SupportsMempool
import Ouroboros.Consensus.Ledger.SupportsPeerSelection
import Ouroboros.Consensus.Mock.Ledger.Address
import Ouroboros.Consensus.Mock.Ledger.State
import qualified Ouroboros.Consensus.Mock.Ledger.UTxO as Mock
Expand Down Expand Up @@ -403,6 +404,9 @@ instance MockProtocolSpecific c ext => CommonProtocolParams (SimpleBlock c ext)
maxHeaderSize = const 2000000
maxTxSize = const 2000000

instance LedgerSupportsPeerSelection (SimpleBlock c ext) where
getPeers = const []

{-------------------------------------------------------------------------------
Support for the mempool
-------------------------------------------------------------------------------}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ library
Ouroboros.Consensus.Shelley.Ledger.Mempool
Ouroboros.Consensus.Shelley.Ledger.NetworkProtocolVersion
Ouroboros.Consensus.Shelley.Ledger.Query
Ouroboros.Consensus.Shelley.Ledger.PeerSelection
Ouroboros.Consensus.Shelley.Ledger.TPraos
Ouroboros.Consensus.Shelley.Node
Ouroboros.Consensus.Shelley.Node.Serialisation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ import Ouroboros.Consensus.Shelley.Ledger.Integrity as X
import Ouroboros.Consensus.Shelley.Ledger.Ledger as X
import Ouroboros.Consensus.Shelley.Ledger.Mempool as X
import Ouroboros.Consensus.Shelley.Ledger.NetworkProtocolVersion as X
import Ouroboros.Consensus.Shelley.Ledger.PeerSelection as X ()
import Ouroboros.Consensus.Shelley.Ledger.Query as X
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}

{-# OPTIONS_GHC -Wno-orphans #-}
module Ouroboros.Consensus.Shelley.Ledger.PeerSelection () where

import Data.Bifunctor (second)
import Data.Foldable (toList)
import Data.List (sortOn)
import Data.List.NonEmpty (NonEmpty)
import qualified Data.List.NonEmpty as NE
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import Data.Maybe (catMaybes)
import Data.Ord (Down (..))

import Ouroboros.Consensus.Ledger.SupportsPeerSelection

import qualified Shelley.Spec.Ledger.Delegation.Certificates as SL
import qualified Shelley.Spec.Ledger.Keys as SL
import qualified Shelley.Spec.Ledger.LedgerState as SL
import qualified Shelley.Spec.Ledger.TxBody as SL

import Ouroboros.Consensus.Shelley.Eras (EraCrypto)
import Ouroboros.Consensus.Shelley.Ledger.Block
import Ouroboros.Consensus.Shelley.Ledger.Ledger

instance LedgerSupportsPeerSelection (ShelleyBlock era) where
getPeers ShelleyLedgerState { shelleyLedgerState } = catMaybes
[ (poolStake,) <$> Map.lookup stakePool poolDomainAddresses
| (stakePool, poolStake) <- orderByStake poolDistr
]
where
poolDistr :: SL.PoolDistr (EraCrypto era)
poolDistr = SL.nesPd shelleyLedgerState

-- | Sort stake pools by descending stake
orderByStake ::
SL.PoolDistr (EraCrypto era)
-> [(SL.KeyHash 'SL.StakePool (EraCrypto era), PoolStake)]
orderByStake =
sortOn (Down . snd)
. map (second SL.individualPoolStake)
. Map.toList
. SL.unPoolDistr

futurePoolParams, poolParams ::
Map (SL.KeyHash 'SL.StakePool (EraCrypto era)) (SL.PoolParams era)
(futurePoolParams, poolParams) =
(SL._fPParams pstate, SL._pParams pstate)
where
pstate :: SL.PState era
pstate =
SL._pstate
. SL._delegationState
. SL.esLState
. SL.nesEs
$ shelleyLedgerState

relayToDomainAddress :: SL.StakePoolRelay -> DomainAddress
relayToDomainAddress = undefined

-- | Note that a stake pool can have multiple registered relays
pparamsDomainAddresses ::
SL.PoolParams era
-> Maybe (NonEmpty DomainAddress)
pparamsDomainAddresses =
NE.nonEmpty . map relayToDomainAddress . toList . SL._poolRelays

-- | Combine the stake pools registered in the future and the current pool
-- parameters, and remove duplicates.
poolDomainAddresses ::
Map (SL.KeyHash 'SL.StakePool (EraCrypto era)) (NonEmpty DomainAddress)
poolDomainAddresses =
Map.unionWith
(\futureRelays currentRelays -> NE.nub (futureRelays <> currentRelays))
(Map.mapMaybe pparamsDomainAddresses futurePoolParams)
(Map.mapMaybe pparamsDomainAddresses poolParams)
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ import Ouroboros.Consensus.Ledger.CommonProtocolParams
import Ouroboros.Consensus.Ledger.Inspect
import Ouroboros.Consensus.Ledger.Query
import Ouroboros.Consensus.Ledger.SupportsMempool
import Ouroboros.Consensus.Ledger.SupportsPeerSelection
import Ouroboros.Consensus.Ledger.SupportsProtocol
import Ouroboros.Consensus.Node.InitStorage
import Ouroboros.Consensus.Node.NetworkProtocolVersion
Expand Down Expand Up @@ -373,6 +374,9 @@ instance HasNestedContent Header BlockA where
instance ReconstructNestedCtxt Header BlockA
-- Use defaults

instance LedgerSupportsPeerSelection BlockA where
getPeers = const []

data UpdateA =
ProposalSubmitted
| ProposalStable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import Ouroboros.Consensus.Ledger.CommonProtocolParams
import Ouroboros.Consensus.Ledger.Inspect
import Ouroboros.Consensus.Ledger.Query
import Ouroboros.Consensus.Ledger.SupportsMempool
import Ouroboros.Consensus.Ledger.SupportsPeerSelection
import Ouroboros.Consensus.Ledger.SupportsProtocol
import Ouroboros.Consensus.Node.InitStorage
import Ouroboros.Consensus.Node.NetworkProtocolVersion
Expand Down Expand Up @@ -320,6 +321,9 @@ instance ReconstructNestedCtxt Header BlockB
instance InspectLedger BlockB where
-- Use defaults

instance LedgerSupportsPeerSelection BlockB where
getPeers = const []

instance NodeInitStorage BlockB where
nodeCheckIntegrity _ _ = True

Expand Down
2 changes: 2 additions & 0 deletions ouroboros-consensus/ouroboros-consensus.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ library
Ouroboros.Consensus.HardFork.Combinator.InjectTxs
Ouroboros.Consensus.HardFork.Combinator.Ledger
Ouroboros.Consensus.HardFork.Combinator.Ledger.CommonProtocolParams
Ouroboros.Consensus.HardFork.Combinator.Ledger.PeerSelection
Ouroboros.Consensus.HardFork.Combinator.Ledger.Query
Ouroboros.Consensus.HardFork.Combinator.Mempool
Ouroboros.Consensus.HardFork.Combinator.Nary
Expand Down Expand Up @@ -113,6 +114,7 @@ library
Ouroboros.Consensus.Ledger.Inspect
Ouroboros.Consensus.Ledger.Query
Ouroboros.Consensus.Ledger.SupportsMempool
Ouroboros.Consensus.Ledger.SupportsPeerSelection
Ouroboros.Consensus.Ledger.SupportsProtocol
Ouroboros.Consensus.Mempool
Ouroboros.Consensus.Mempool.API
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ import Ouroboros.Consensus.HardFork.Combinator.Protocol as X
import Ouroboros.Consensus.HardFork.Combinator.Ledger.CommonProtocolParams as X
()

-- Instance for 'LedgerSupportsPeerSelection'
import Ouroboros.Consensus.HardFork.Combinator.Ledger.PeerSelection as X
()

-- Instances for 'ShowQuery' and 'QueryLedger'
-- Definition of 'Query', required for serialisation code
import Ouroboros.Consensus.HardFork.Combinator.Ledger.Query as X
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import Ouroboros.Consensus.Ledger.CommonProtocolParams
import Ouroboros.Consensus.Ledger.Inspect
import Ouroboros.Consensus.Ledger.Query
import Ouroboros.Consensus.Ledger.SupportsMempool
import Ouroboros.Consensus.Ledger.SupportsPeerSelection
import Ouroboros.Consensus.Ledger.SupportsProtocol
import Ouroboros.Consensus.Node.InitStorage
import Ouroboros.Consensus.Storage.Serialisation
Expand All @@ -60,6 +61,7 @@ class ( LedgerSupportsProtocol blk
, ConvertRawHash blk
, ReconstructNestedCtxt Header blk
, CommonProtocolParams blk
, LedgerSupportsPeerSelection blk
, ConfigSupportsNode blk
, NodeInitStorage blk
-- Instances required to support testing
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{-# OPTIONS_GHC -Wno-orphans #-}
module Ouroboros.Consensus.HardFork.Combinator.Ledger.PeerSelection () where

import Data.SOP.Strict

import Ouroboros.Consensus.Ledger.SupportsPeerSelection

import Ouroboros.Consensus.HardFork.Combinator.Abstract
import Ouroboros.Consensus.HardFork.Combinator.Basics
import Ouroboros.Consensus.HardFork.Combinator.Ledger ()
import qualified Ouroboros.Consensus.HardFork.Combinator.State as State

instance CanHardFork xs => LedgerSupportsPeerSelection (HardForkBlock xs) where
getPeers =
hcollapse
. hcmap proxySingle (K . getPeers)
. State.tip
. hardForkLedgerStatePerEra
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import Ouroboros.Consensus.HardFork.Combinator.Basics
import Ouroboros.Consensus.HardFork.Combinator.Forging ()
import Ouroboros.Consensus.HardFork.Combinator.Ledger.CommonProtocolParams
()
import Ouroboros.Consensus.HardFork.Combinator.Ledger.PeerSelection ()
import Ouroboros.Consensus.HardFork.Combinator.Node.InitStorage ()
import Ouroboros.Consensus.HardFork.Combinator.Serialisation

Expand Down
10 changes: 10 additions & 0 deletions ouroboros-consensus/src/Ouroboros/Consensus/Ledger/Dual.hs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ import Ouroboros.Consensus.Ledger.Extended
import Ouroboros.Consensus.Ledger.Inspect
import Ouroboros.Consensus.Ledger.Query
import Ouroboros.Consensus.Ledger.SupportsMempool
import Ouroboros.Consensus.Ledger.SupportsPeerSelection
import Ouroboros.Consensus.Ledger.SupportsProtocol
import Ouroboros.Consensus.Util (ShowProxy (..))
import Ouroboros.Consensus.Util.Condense
Expand Down Expand Up @@ -694,6 +695,15 @@ instance InspectLedger m => InspectLedger (DualBlock m a) where
(dualLedgerStateMain before)
(dualLedgerStateMain after)


{-------------------------------------------------------------------------------
PeerSelection
-------------------------------------------------------------------------------}

instance LedgerSupportsPeerSelection m
=> LedgerSupportsPeerSelection (DualBlock m a) where
getPeers = getPeers . dualLedgerStateMain

{-------------------------------------------------------------------------------
Forging
-------------------------------------------------------------------------------}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module Ouroboros.Consensus.Ledger.SupportsPeerSelection (
LedgerSupportsPeerSelection (..)
, PoolStake
-- * Re-exports for convenience
, DomainAddress (..)
, Domain
, PortNumber
) where

import Data.List.NonEmpty (NonEmpty)

import Ouroboros.Network.PeerSelection.RootPeersDNS (Domain,
DomainAddress (..), PortNumber)

import Ouroboros.Consensus.Ledger.Abstract (LedgerState)

-- | The relative stake of the stakepool. A value in the [0, 1] range.
type PoolStake = Rational

class LedgerSupportsPeerSelection blk where
-- | Return peers registered in the ledger ordered by descending 'PoolStake'.
--
-- For example, for Shelley, the relays that have been registered in the
-- ledger for the respective stake pools will be returned.
--
-- Ledgers/blocks that don't support staking can return an empty list.
getPeers :: LedgerState blk -> [(PoolStake, NonEmpty DomainAddress)]
2 changes: 2 additions & 0 deletions ouroboros-consensus/src/Ouroboros/Consensus/Node/Run.hs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import Ouroboros.Consensus.Ledger.CommonProtocolParams
import Ouroboros.Consensus.Ledger.Inspect
import Ouroboros.Consensus.Ledger.Query
import Ouroboros.Consensus.Ledger.SupportsMempool
import Ouroboros.Consensus.Ledger.SupportsPeerSelection
import Ouroboros.Consensus.Ledger.SupportsProtocol
import Ouroboros.Consensus.Node.InitStorage
import Ouroboros.Consensus.Node.NetworkProtocolVersion
Expand Down Expand Up @@ -86,6 +87,7 @@ class ( LedgerSupportsProtocol blk
, SerialiseDiskConstraints blk
, SerialiseNodeToNodeConstraints blk
, SerialiseNodeToClientConstraints blk
, LedgerSupportsPeerSelection blk
, NodeInitStorage blk
, Show (CannotForge blk)
, Show (ForgeStateInfo blk)
Expand Down
19 changes: 19 additions & 0 deletions ouroboros-consensus/src/Ouroboros/Consensus/NodeKernel.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ module Ouroboros.Consensus.NodeKernel (
, initNodeKernel
, getMempoolReader
, getMempoolWriter
, getPeersFromCurrentLedger
) where

import Control.Monad
import Control.Monad.Except
import Data.Hashable (Hashable)
import Data.List.NonEmpty (NonEmpty)
import Data.Map.Strict (Map)
import Data.Maybe (isJust)
import Data.Proxy
Expand Down Expand Up @@ -56,6 +58,7 @@ import Ouroboros.Consensus.HeaderValidation
import Ouroboros.Consensus.Ledger.Abstract
import Ouroboros.Consensus.Ledger.Extended
import Ouroboros.Consensus.Ledger.SupportsMempool
import Ouroboros.Consensus.Ledger.SupportsPeerSelection
import Ouroboros.Consensus.Ledger.SupportsProtocol
import Ouroboros.Consensus.Mempool
import Ouroboros.Consensus.Node.Run
Expand Down Expand Up @@ -652,3 +655,19 @@ getMempoolWriter mempool = Inbound.TxSubmissionMempoolWriter
map (txId . fst) . filter (isMempoolTxAdded . snd) <$>
addTxs mempool txs
}

{-------------------------------------------------------------------------------
PeerSelection integration
-------------------------------------------------------------------------------}

-- | Retrieve the peers registered in the current chain/ledger state by
-- descending stake.
--
-- For example, for Shelley, this will return the stake pool relays ordered by
-- descending stake.
getPeersFromCurrentLedger ::
(IOLike m, LedgerSupportsPeerSelection blk)
=> NodeKernel m remotePeer localPeer blk
-> STM m [(PoolStake, NonEmpty DomainAddress)]
getPeersFromCurrentLedger kernel =
getPeers . ledgerState <$> ChainDB.getCurrentLedger (getChainDB kernel)
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ module Ouroboros.Network.PeerSelection.RootPeersDNS (
DNS.Domain,
DNS.TTL,
IPv4,

-- * Socket type re-exports
Socket.PortNumber,
) where

import Data.Word (Word32)
Expand Down

0 comments on commit c8fb01c

Please sign in to comment.