Skip to content
This repository was archived by the owner on Aug 18, 2020. It is now read-only.

Commit 7aba046

Browse files
committed
[CBR-481/482] Separate OBFT functions into pure and impure
1 parent b030b78 commit 7aba046

File tree

4 files changed

+78
-27
lines changed

4 files changed

+78
-27
lines changed

chain/cardano-sl-chain.cabal

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ library
9191
Pos.Chain.Txp.Undo
9292

9393
Pos.Chain.Lrc.Fts
94+
Pos.Chain.Lrc.OBFT
9495
Pos.Chain.Lrc.Types
9596
Pos.Chain.Lrc.Error
9697
Pos.Chain.Lrc.Core

chain/src/Pos/Chain/Lrc.hs

+1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ import Pos.Chain.Lrc.Core as X
66
import Pos.Chain.Lrc.Error as X
77
import Pos.Chain.Lrc.Fts as X
88
import Pos.Chain.Lrc.Genesis as X
9+
import Pos.Chain.Lrc.OBFT as X
910
import Pos.Chain.Lrc.RichmenComponent as X
1011
import Pos.Chain.Lrc.Types as X

chain/src/Pos/Chain/Lrc/OBFT.hs

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
module Pos.Chain.Lrc.OBFT
2+
( getSlotLeaderObftPure
3+
, getEpochSlotLeaderScheduleObftPure
4+
) where
5+
6+
import Universum hiding (sort)
7+
8+
import Data.List.NonEmpty ((!!))
9+
import qualified Data.List.NonEmpty as NE (iterate, sort, take)
10+
11+
import Pos.Core (EpochIndex, FlatSlotId, LocalSlotIndex (..),
12+
SlotCount (..), SlotId (..), SlotLeaders, StakeholderId,
13+
flattenEpochOrSlot, slotIdSucc)
14+
15+
-- | Selects the StakeholderId that matches the @SlotId@ index in a
16+
-- @SlotCount@-length epoch.
17+
getSlotLeaderObftPure
18+
:: SlotId
19+
-> SlotCount
20+
-> NonEmpty StakeholderId
21+
-> StakeholderId
22+
getSlotLeaderObftPure slotId slotCount stakeholders =
23+
sortedStakeholders !! leaderIndex
24+
where
25+
-- Ensure the stakeholders are sorted
26+
sortedStakeholders :: NonEmpty StakeholderId
27+
sortedStakeholders = NE.sort stakeholders
28+
--
29+
leaderIndex :: Int
30+
leaderIndex = (fromIntegral flatSlotId :: Int) `mod` (length stakeholders)
31+
--
32+
flatSlotId :: FlatSlotId
33+
flatSlotId = flattenEpochOrSlot slotCount slotId
34+
35+
-- | Selects @SlotCount@ StakeholderIds for the given epoch @EpochIndex@.
36+
getEpochSlotLeaderScheduleObftPure
37+
:: EpochIndex
38+
-> SlotCount
39+
-> NonEmpty StakeholderId
40+
-> SlotLeaders
41+
getEpochSlotLeaderScheduleObftPure epochIndex epochSlotCount stakeholders =
42+
case nonEmpty slotLeaderSchedule of
43+
Just sls -> sls
44+
Nothing -> error "getEpochSlotLeaderScheduleObftPure: Empty slot leader schedule"
45+
where
46+
slotLeaderSchedule =
47+
map (\si -> getSlotLeaderObftPure si epochSlotCount stakeholders)
48+
(NE.take (fromIntegral $ numEpochSlots)
49+
(NE.iterate (slotIdSucc epochSlotCount) startSlotId))
50+
--
51+
startSlotId :: SlotId
52+
startSlotId = SlotId epochIndex (UnsafeLocalSlotIndex 0)
53+
--
54+
numEpochSlots :: Word64
55+
numEpochSlots = getSlotCount $ epochSlotCount

db/src/Pos/DB/Lrc/OBFT.hs

+21-27
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ import Universum
88
import Pos.Chain.Delegation (ProxySKBlockInfo)
99
import Pos.Chain.Genesis (configGenesisWStakeholders)
1010
import qualified Pos.Chain.Genesis as Genesis (Config (..))
11-
import Pos.Core (EpochIndex, FlatSlotId, LocalSlotIndex (..),
12-
SlotCount (..), SlotId (..), SlotLeaders, StakeholderId,
13-
flattenEpochOrSlot, pcEpochSlots, slotIdSucc)
11+
import Pos.Chain.Lrc (getEpochSlotLeaderScheduleObftPure,
12+
getSlotLeaderObftPure)
13+
import Pos.Core (EpochIndex, SlotCount (..), SlotId (..), SlotLeaders,
14+
StakeholderId, pcEpochSlots)
1415
import Pos.DB (MonadDBRead)
1516
import Pos.DB.Delegation (getDlgTransPsk)
1617

17-
import Data.List ((!!))
1818
import UnliftIO (MonadUnliftIO)
1919

2020
-- | This function selects the current slot leaders by obtaining the
@@ -32,32 +32,26 @@ getSlotLeaderObft genesisConfig si = do
3232
stakeholders :: [StakeholderId]
3333
stakeholders = sort $ configGenesisWStakeholders genesisConfig
3434
--
35-
flatSlotId :: FlatSlotId
36-
flatSlotId =
37-
flattenEpochOrSlot (pcEpochSlots (Genesis.configProtocolConstants
38-
genesisConfig))
39-
si
40-
--
41-
leaderIndex :: Int
42-
leaderIndex = (fromIntegral flatSlotId :: Int) `mod` (length stakeholders)
35+
epochSlotCount :: SlotCount
36+
epochSlotCount =
37+
pcEpochSlots (Genesis.configProtocolConstants genesisConfig)
4338
--
4439
currentSlotGenesisSId :: StakeholderId
45-
currentSlotGenesisSId = stakeholders !! leaderIndex
40+
currentSlotGenesisSId =
41+
case (nonEmpty stakeholders) of
42+
Just s -> getSlotLeaderObftPure si epochSlotCount s
43+
Nothing -> error "getSlotLeaderObft: Empty list of stakeholders"
4644

4745
-- | Generates the full slot leader schedule for an epoch (10*k slots long).
4846
getEpochSlotLeaderScheduleObft
49-
:: (MonadDBRead m, MonadUnliftIO m)
50-
=> Genesis.Config -> EpochIndex -> m SlotLeaders
51-
getEpochSlotLeaderScheduleObft genesisConfig ei = do
52-
leaders <-
53-
map fst
54-
<$> mapM (getSlotLeaderObft genesisConfig)
55-
(take (fromIntegral $ epochSlotCount)
56-
(iterate (slotIdSucc epochSlots) startSlotId))
57-
case nonEmpty leaders of
58-
Just l -> pure l
59-
Nothing -> error "getEpochSlotLeaderScheduleObft: Empty list of leaders"
47+
:: Genesis.Config -> EpochIndex -> SlotLeaders
48+
getEpochSlotLeaderScheduleObft genesisConfig ei =
49+
case nonEmpty stakeholders of
50+
Just s -> getEpochSlotLeaderScheduleObftPure ei epochSlotCount s
51+
Nothing -> error "getEpochSlotLeaderScheduleObft: Empty list of stakeholders"
6052
where
61-
startSlotId = SlotId ei (UnsafeLocalSlotIndex 0)
62-
epochSlots = pcEpochSlots (Genesis.configProtocolConstants genesisConfig)
63-
epochSlotCount = getSlotCount $ epochSlots
53+
-- We assume here that the genesis bootstrap stakeholders list
54+
-- is nonempty
55+
stakeholders :: [StakeholderId]
56+
stakeholders = sort $ configGenesisWStakeholders genesisConfig
57+
epochSlotCount = pcEpochSlots (Genesis.configProtocolConstants genesisConfig)

0 commit comments

Comments
 (0)