Skip to content

Commit

Permalink
PLT-6426: Fix epoch state endpoint (#221)
Browse files Browse the repository at this point in the history
Signed-off-by: Ana Pantilie <[email protected]>
  • Loading branch information
ana-pantilie authored Nov 6, 2023
1 parent 7a3e6d8 commit e6974c7
Show file tree
Hide file tree
Showing 10 changed files with 301 additions and 162 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ import Control.Monad (filterM, forM_, when)
import Control.Monad.Except (ExceptT)
import Control.Monad.Trans (MonadTrans (lift))

import Data.Aeson (FromJSON (parseJSON), ToJSON (toJSON), Value (Object), object, (.:), (.=))
import Data.Aeson (FromJSON, ToJSON, Value (Object), object, (.:), (.:?), (.=))
import Data.ByteString.Base16 qualified as Base16
import Data.ByteString.Lazy qualified as BS
import Data.Coerce (coerce)
Expand All @@ -112,6 +112,7 @@ import Database.SQLite.Simple.QQ (sql)

import GHC.Generics (Generic)

import Data.Aeson.Types (FromJSON (parseJSON), ToJSON (toJSON))
import Data.Void (Void)
import Marconi.ChainIndex.Legacy.Error (
IndexerError (CantInsertEvent, CantQueryIndexer, CantRollback, CantStartIndexer),
Expand All @@ -124,6 +125,7 @@ import Marconi.ChainIndex.Legacy.Utils (
getBlockNoFromChainTip,
isBlockRollbackable,
)
import Marconi.ChainIndex.Legacy.Utils qualified as Util
import Marconi.Core.Storable (
Buffered (persistToStorage),
HasPoint (getPoint),
Expand Down Expand Up @@ -169,19 +171,18 @@ data instance StorableEvent EpochStateHandle = EpochStateEvent
, epochStateEventEpochNo :: Maybe C.EpochNo
, epochStateEventNonce :: Ledger.Nonce
, epochStateEventSDD :: Map C.PoolId C.Lovelace
, epochStateEventSlotNo :: C.SlotNo
, epochStateEventBlockHeaderHash :: C.Hash C.BlockHeader
, epochStateEventChainPoint :: C.ChainPoint
, epochStateEventBlockNo :: C.BlockNo
, epochStateEventChainTip :: C.ChainTip
-- ^ Actual tip of the chain
, epochStateEventIsFirstEventOfEpoch :: Bool
}
deriving (Eq, Show)
deriving stock (Eq, Show)

type instance StorablePoint EpochStateHandle = C.ChainPoint

instance HasPoint (StorableEvent EpochStateHandle) C.ChainPoint where
getPoint (EpochStateEvent _ _ _ _ s bhh _ _ _) = C.ChainPoint s bhh
getPoint (EpochStateEvent _ _ _ _ chainPoint _ _ _) = chainPoint

data instance StorableQuery EpochStateHandle
= -- See Note [Active stake pool delegation query]
Expand All @@ -193,7 +194,7 @@ data instance StorableResult EpochStateHandle
= ActiveSDDByEpochNoResult [EpochSDDRow]
| NonceByEpochNoResult (Maybe EpochNonceRow)
| LedgerStateAtPointResult (Maybe (O.ExtLedgerState (O.CardanoBlock O.StandardCrypto)))
deriving (Eq, Show)
deriving stock (Eq, Show)

type EpochStateIndex = State EpochStateHandle

Expand All @@ -208,7 +209,8 @@ toStorableEvent
-- ^ Is the first event of the current epoch
-> StorableEvent EpochStateHandle
toStorableEvent extLedgerState slotNo bhh bn chainTip securityParam isFirstEventOfEpoch = do
let doesStoreLedgerState =
let chainPoint = C.ChainPoint slotNo bhh
doesStoreLedgerState =
isBlockRollbackable securityParam bn (getBlockNoFromChainTip chainTip)
|| isBlockRollbackable securityParam (bn + 1) (getBlockNoFromChainTip chainTip)
|| isFirstEventOfEpoch
Expand All @@ -217,8 +219,7 @@ toStorableEvent extLedgerState slotNo bhh bn chainTip securityParam isFirstEvent
(getEpochNo extLedgerState)
(getEpochNonce extLedgerState)
(getStakeMap extLedgerState)
slotNo
bhh
chainPoint
bn
chainTip
isFirstEventOfEpoch
Expand Down Expand Up @@ -293,20 +294,24 @@ data EpochSDDRow = EpochSDDRow
{ epochSDDRowEpochNo :: !C.EpochNo
, epochSDDRowPoolId :: !C.PoolId
, epochSDDRowLovelace :: !C.Lovelace
, epochSDDRowSlotNo :: !C.SlotNo
, epochSDDRowBlockHeaderHash :: !(C.Hash C.BlockHeader)
, epochSDDRowSlotNo :: !(Maybe C.SlotNo)
, epochSDDRowBlockHeaderHash :: !(Maybe (C.Hash C.BlockHeader))
, epochSDDRowBlockNo :: !C.BlockNo
}
deriving (Eq, Ord, Show, Generic, SQL.FromRow, SQL.ToRow)
deriving stock (Eq, Ord, Show, Generic)
deriving anyclass (SQL.FromRow, SQL.ToRow)

instance FromJSON EpochSDDRow where
parseJSON (Object v) =
EpochSDDRow
<$> (C.EpochNo <$> v .: "epochNo")
<*> v .: "poolId"
<*> v .: "lovelace"
<*> (C.SlotNo <$> v .: "slotNo")
<*> v .: "blockHeaderHash"
<*> v
.: "poolId"
<*> v
.: "lovelace"
<*> (fmap C.SlotNo <$> v .:? "slotNo")
<*> v
.: "blockHeaderHash"
<*> (C.BlockNo <$> v .: "blockNo")
parseJSON _ = mempty

Expand All @@ -316,15 +321,15 @@ instance ToJSON EpochSDDRow where
(C.EpochNo epochNo)
poolId
lovelace
(C.SlotNo slotNo)
slotNo
blockHeaderHash
(C.BlockNo blockNo)
) =
object
[ "epochNo" .= epochNo
, "poolId" .= poolId
, "lovelace" .= lovelace
, "slotNo" .= slotNo
, "slotNo" .= fmap C.unSlotNo slotNo
, "blockHeaderHash" .= blockHeaderHash
, "blockNo" .= blockNo
]
Expand Down Expand Up @@ -353,19 +358,21 @@ getEpochNonce extLedgerState =
data EpochNonceRow = EpochNonceRow
{ epochNonceRowEpochNo :: !C.EpochNo
, epochNonceRowNonce :: !Ledger.Nonce
, epochNonceRowSlotNo :: !C.SlotNo
, epochNonceRowBlockHeaderHash :: !(C.Hash C.BlockHeader)
, epochNonceRowSlotNo :: !(Maybe C.SlotNo)
, epochNonceRowBlockHeaderHash :: !(Maybe (C.Hash C.BlockHeader))
, epochNonceRowBlockNo :: !C.BlockNo
}
deriving (Eq, Ord, Show, Generic, SQL.FromRow, SQL.ToRow)
deriving stock (Eq, Ord, Show, Generic)
deriving anyclass (SQL.FromRow, SQL.ToRow)

instance FromJSON EpochNonceRow where
parseJSON (Object v) =
EpochNonceRow
<$> (C.EpochNo <$> v .: "epochNo")
<*> (Ledger.Nonce <$> v .: "nonce")
<*> (C.SlotNo <$> v .: "slotNo")
<*> v .: "blockHeaderHash"
<*> (fmap C.SlotNo <$> v .:? "slotNo")
<*> v
.: "blockHeaderHash"
<*> (C.BlockNo <$> v .: "blockNo")
parseJSON _ = mempty

Expand All @@ -374,7 +381,7 @@ instance ToJSON EpochNonceRow where
( EpochNonceRow
(C.EpochNo epochNo)
nonce
(C.SlotNo slotNo)
slotNo
blockHeaderHash
(C.BlockNo blockNo)
) =
Expand All @@ -384,7 +391,7 @@ instance ToJSON EpochNonceRow where
in object
[ "epochNo" .= epochNo
, "nonce" .= nonceValue
, "slotNo" .= slotNo
, "slotNo" .= fmap C.unSlotNo slotNo
, "blockHeaderHash" .= blockHeaderHash
, "blockNo" .= blockNo
]
Expand All @@ -394,7 +401,7 @@ data LedgerStateFileMetadata = LedgerStateFileMetadata
, lsfMetaBlockHeaderHash :: !(C.Hash C.BlockHeader)
, lsfMetaBlockNo :: !C.BlockNo
}
deriving (Show)
deriving stock (Show)

instance Buffered EpochStateHandle where
-- We should only store on disk SDD from the last slot of each epoch.
Expand Down Expand Up @@ -464,8 +471,7 @@ instance Buffered EpochStateHandle where
maybeEpochNo
_
_
slotNo
blockHeaderHash
chainPoint
blockNo
chainTip
isFirstEventOfEpoch
Expand All @@ -477,6 +483,9 @@ instance Buffered EpochStateHandle where
isLastImmutableBeforeRollbackable =
isBlockRollbackable securityParam (blockNo + 1) (getBlockNoFromChainTip chainTip)
when (isRollbackable || isLastImmutableBeforeRollbackable || isFirstEventOfEpoch) $ do
-- The conditions above make it impossible for the ChainPoint to be at genesis,
-- so we should be able to extract the slot and the hash safely.
let (slotNo, blockHeaderHash) = Util.extractSlotNoAndHash chainPoint
writeLedgerState
ledgerState
slotNo
Expand Down Expand Up @@ -552,37 +561,39 @@ instance Buffered EpochStateHandle where
eventToEpochSDDRows
:: StorableEvent EpochStateHandle
-> [EpochSDDRow]
eventToEpochSDDRows (EpochStateEvent _ maybeEpochNo _ m slotNo blockHeaderHash blockNo _ _) =
mapMaybe
( \(keyHash, lovelace) ->
fmap
( \epochNo ->
EpochSDDRow
epochNo
keyHash
lovelace
slotNo
blockHeaderHash
blockNo
)
maybeEpochNo
)
$ Map.toList m
eventToEpochSDDRows (EpochStateEvent _ maybeEpochNo _ m chainPoint blockNo _ _) =
let (slotNo, blockHeaderHash) = Util.chainPointToMaybes chainPoint
in mapMaybe
( \(keyHash, lovelace) ->
fmap
( \epochNo ->
EpochSDDRow
epochNo
keyHash
lovelace
slotNo
blockHeaderHash
blockNo
)
maybeEpochNo
)
$ Map.toList m

eventToEpochNonceRow
:: StorableEvent EpochStateHandle
-> Maybe EpochNonceRow
eventToEpochNonceRow (EpochStateEvent _ maybeEpochNo nonce _ slotNo blockHeaderHash blockNo _ _) =
fmap
( \epochNo ->
EpochNonceRow
epochNo
nonce
slotNo
blockHeaderHash
blockNo
)
maybeEpochNo
eventToEpochNonceRow (EpochStateEvent _ maybeEpochNo nonce _ chainPoint blockNo _ _) =
let (slotNo, blockHeaderHash) = Util.chainPointToMaybes chainPoint
in fmap
( \epochNo ->
EpochNonceRow
epochNo
nonce
slotNo
blockHeaderHash
blockNo
)
maybeEpochNo

instance Queryable EpochStateHandle where
queryStorage
Expand Down Expand Up @@ -629,7 +640,8 @@ instance Queryable EpochStateHandle where
(EpochStateHandle{_epochStateHandleTopLevelCfg, _epochStateHandleLedgerStateDirPath})
(LedgerStateAtPointQuery (C.ChainPoint slotNo _)) =
liftSQLError CantQueryIndexer $ do
case List.find (\e -> epochStateEventSlotNo e == slotNo) (toList events) of
let extractSlotNo = fst . Util.extractSlotNoAndHash . epochStateEventChainPoint
case List.find (\e -> extractSlotNo e == slotNo) (toList events) of
Nothing -> do
ledgerStateFilePaths <- listDirectory _epochStateHandleLedgerStateDirPath
let ledgerStateFilePath =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ module Marconi.ChainIndex.Legacy.Utils (
toException,
chainPointOrGenesis,
addressesToPredicate,
extractSlotNoAndHash,
chainPointToMaybes,
) where

import Cardano.Api qualified as C
Expand Down Expand Up @@ -167,3 +169,14 @@ shelleyBasedToCardanoEra C.MaryEra = Just C.ShelleyBasedEraMary
shelleyBasedToCardanoEra C.AlonzoEra = Just C.ShelleyBasedEraAlonzo
shelleyBasedToCardanoEra C.BabbageEra = Just C.ShelleyBasedEraBabbage
shelleyBasedToCardanoEra C.ConwayEra = Just C.ShelleyBasedEraConway

extractSlotNoAndHash :: C.ChainPoint -> (C.SlotNo, C.Hash C.BlockHeader)
extractSlotNoAndHash (C.ChainPoint s h) = (s, h)
extractSlotNoAndHash C.ChainPointAtGenesis =
error $
"Expected chain point later than genesis."
<> " This is an application bug, please open an issue at https://github.com/input-output-hk/marconi."

chainPointToMaybes :: C.ChainPoint -> (Maybe C.SlotNo, Maybe (C.Hash C.BlockHeader))
chainPointToMaybes (C.ChainPoint s h) = (Just s, Just h)
chainPointToMaybes C.ChainPointAtGenesis = (Nothing, Nothing)
Loading

0 comments on commit e6974c7

Please sign in to comment.