1+ {-# LANGUAGE ApplicativeDo #-}
12{-# LANGUAGE FlexibleContexts #-}
23{-# LANGUAGE GADTs #-}
34{-# LANGUAGE LambdaCase #-}
4- {-# LANGUAGE RankNTypes #-}
5- {-# LANGUAGE TypeOperators #-}
65
76module Cardano.Rpc.Server.NodeKernelAccess.Internal
87 ( mkNodeKernelAccess
@@ -15,33 +14,64 @@ import Cardano.Api.Consensus qualified as Consensus
1514import Cardano.Rpc.Server.Internal.Monad (MonadRpc , grab )
1615import Cardano.Rpc.Server.NodeKernelAccess
1716
18- import RIO (throwIO )
17+ import RIO (HasCallStack , atomically , throwIO , tshow )
1918
2019import Data.ByteString (ByteString )
2120import Data.ByteString.Lazy qualified as BSL
2221import Data.IORef
2322import Network.GRPC.Spec
2423
2524-- | Construct 'NodeKernelAccessF' from a consensus 'Consensus.NodeKernel'.
26- -- Only 'nkaFetchBlock' is implemented; snapshot and submit callbacks are stubbed.
25+ -- Only 'nkaFetchBlock' and 'nkaSlotToUTCTime' are implemented; snapshot and submit callbacks
26+ -- throw 'GrpcUnimplemented'. Non-Cardano block types throw 'GrpcInternal'.
2727mkNodeKernelAccess
28- :: MonadIO m
28+ :: ( HasCallStack , MonadIO m )
2929 => Consensus. BlockType blk
30- -- ^ Block type witness, used to bring 'HeaderHash' constraint into scope
30+ -- ^ Block type witness
3131 -> Consensus. NodeKernel IO addrNTN addrNTC blk
3232 -- ^ Consensus node kernel
3333 -> NodeKernelAccessF m
34- mkNodeKernelAccess blockType nodeKernel =
34+ mkNodeKernelAccess Consensus. CardanoBlockType nodeKernel = do
35+ let chainDb = Consensus. getChainDB nodeKernel
36+ topConfig = Consensus. getTopLevelConfig nodeKernel
3537 NodeKernelAccessF
36- { nkaWithSnapshot = \ _ -> error " nkaWithSnapshot: not yet implemented (NKA query migration pending)"
37- , nkaSubmitTx = \ _ -> error " nkaSubmitTx: not yet implemented (NKA submit migration pending)"
38- , nkaFetchBlock = fetchBlock blockType $ Consensus. getChainDB nodeKernel
38+ { nkaWithSnapshot = \ _ -> throwUnimplemented " nkaWithSnapshot"
39+ , nkaSubmitTx = \ _ -> throwUnimplemented " nkaSubmitTx"
40+ , nkaFetchBlock = fetchBlock chainDb
41+ , nkaSystemStart = Consensus. nodeSystemStart topConfig
42+ , nkaEraHistory = getEraHistory chainDb topConfig
3943 }
44+ mkNodeKernelAccess blockType _ =
45+ let ex =
46+ GrpcException
47+ { grpcError = GrpcInternal
48+ , grpcErrorMessage = Just $ " RPC requires CardanoBlockType, got " <> tshow blockType
49+ , grpcErrorDetails = Nothing
50+ , grpcErrorMetadata = []
51+ }
52+ in NodeKernelAccessF
53+ { nkaWithSnapshot = \ _ -> throwIO ex
54+ , nkaSubmitTx = \ _ -> throwIO ex
55+ , nkaFetchBlock = \ _ _ -> throwIO ex
56+ , nkaSystemStart = error $ " RPC requires CardanoBlockType, got " <> show blockType
57+ , nkaEraHistory = throwIO ex
58+ }
59+
60+ -- | Throw a gRPC UNIMPLEMENTED error for callbacks not yet migrated to NKA.
61+ throwUnimplemented :: (HasCallStack , MonadIO m ) => Text -> m a
62+ throwUnimplemented name =
63+ throwIO
64+ GrpcException
65+ { grpcError = GrpcUnimplemented
66+ , grpcErrorMessage = Just $ name <> " : not yet implemented"
67+ , grpcErrorDetails = Nothing
68+ , grpcErrorMetadata = []
69+ }
4070
4171-- | Grab the current 'NodeKernelAccessF' from the environment, or throw
4272-- gRPC UNAVAILABLE if the node kernel has not yet initialised.
4373grabNodeKernelAccess
44- :: MonadRpc e m
74+ :: ( HasCallStack , MonadRpc e m )
4575 => m (NodeKernelAccessF m )
4676grabNodeKernelAccess =
4777 grab >>= liftIO . readIORef >>= \ case
@@ -56,31 +86,33 @@ grabNodeKernelAccess =
5686 Just nodeKernelAccess ->
5787 pure nodeKernelAccess
5888
89+ -- | Read the current era history from the live ledger state.
90+ getEraHistory
91+ :: MonadIO m
92+ => Consensus. ChainDB IO (Consensus. CardanoBlock Consensus. StandardCrypto )
93+ -> Consensus. TopLevelConfig (Consensus. CardanoBlock Consensus. StandardCrypto )
94+ -> m EraHistory
95+ getEraHistory chainDb topConfig = do
96+ extLedgerState <- liftIO . atomically $ Consensus. getCurrentLedger chainDb
97+ let summary =
98+ Consensus. hardForkSummary (Consensus. configLedger topConfig) (Consensus. ledgerState extLedgerState)
99+ pure . EraHistory $ Consensus. mkInterpreter summary
100+
59101-- | Fetch a raw block and its block number from ChainDB by slot and header hash.
60102fetchBlock
61103 :: MonadIO m
62- => Consensus. BlockType blk
63- -- ^ Block type witness
64- -> Consensus. ChainDB IO blk
104+ => Consensus. ChainDB IO (Consensus. CardanoBlock Consensus. StandardCrypto )
65105 -- ^ Chain database
66106 -> SlotNo
67107 -- ^ Block slot number
68108 -> Hash BlockHeader
69109 -- ^ Block header hash
70110 -> m (Maybe (ByteString , BlockNo ))
71111 -- ^ Raw CBOR bytes and block number, or 'Nothing' if not found
72- fetchBlock blockType chainDB slot (HeaderHash shortHash) =
73- withBlockTypeConstraints blockType $ do
74- let point = Consensus. RealPoint slot (Consensus. OneEraHash shortHash)
75- rawBytes <- liftIO $ Consensus. getBlockComponent chainDB Consensus. GetRawBlock point
76- typedBlock <- liftIO $ Consensus. getBlockComponent chainDB Consensus. GetBlock point
77- pure $ liftA2 (,) (BSL. toStrict <$> rawBytes) (Consensus. blockNo <$> typedBlock)
78-
79- withBlockTypeConstraints
80- :: Consensus. BlockType blk
81- -> (forall xs . (Consensus. HeaderHash blk ~ Consensus. OneEraHash xs , Consensus. HasHeader blk ) => a )
82- -> a
83- withBlockTypeConstraints = \ case
84- Consensus. CardanoBlockType -> id
85- Consensus. ShelleyBlockType -> id
86- Consensus. ByronBlockType -> id
112+ fetchBlock chainDb slot (HeaderHash shortHash) = do
113+ let point = Consensus. RealPoint slot (Consensus. OneEraHash shortHash)
114+ getComponent component = liftIO $ Consensus. getBlockComponent chainDb component point
115+ getComponent $ do
116+ rawBytes <- BSL. toStrict <$> Consensus. GetRawBlock
117+ blockNumber <- Consensus. blockNo <$> Consensus. GetBlock
118+ pure (rawBytes, blockNumber)
0 commit comments