Skip to content

Commit 81a2c40

Browse files
authored
Merge pull request #1325 from IntersectMBO/mgalazyn/feature/rpc-readerasummary
cardano-rpc: Implement ReadEraSummary gRPC method
2 parents 3419989 + 499fff2 commit 81a2c40

15 files changed

Lines changed: 352 additions & 52 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
project: cardano-rpc
2+
pr: 1325
3+
kind:
4+
- feature
5+
- breaking
6+
description: |
7+
Implement the `ReadEraSummary` gRPC method, returning the era name and the start and end boundaries (Unix-epoch milliseconds, slot, epoch) of every era in the chain's history. The `NodeKernelAccess` type is now abstract; use the functions of `Cardano.Rpc.Server.NodeKernelAccess` instead of its record fields.

cardano-rpc/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Use a dedicated chain indexing service for those.
2121
| [ReadData](https://utxorpc.org/query/spec/#readdatarequest) | ❌ Not supported, needs a chain indexer |
2222
| [ReadTx](https://utxorpc.org/query/spec/#queryservice) | ❌ Not supported, needs a chain indexer |
2323
| [ReadGenesis](https://utxorpc.org/query/spec/#queryservice) | ✅ Supported |
24-
| [ReadEraSummary](https://utxorpc.org/query/spec/#queryservice) | ⬜ Not supported |
24+
| [ReadEraSummary](https://utxorpc.org/query/spec/#queryservice) | ✅ Supported |
2525
| [ReadState](https://utxorpc.org/query/spec/#queryservice) | ⬜ Not supported |
2626

2727
### [SubmitService](https://utxorpc.org/submit/spec/)

cardano-rpc/cardano-rpc.cabal

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ library
7171
Cardano.Rpc.Server.Internal.UtxoRpc.Type.Byron
7272
Cardano.Rpc.Server.Internal.UtxoRpc.Type.Certificate
7373
Cardano.Rpc.Server.Internal.UtxoRpc.Type.ChainPoint
74+
Cardano.Rpc.Server.Internal.UtxoRpc.Type.EraSummary
7475
Cardano.Rpc.Server.Internal.UtxoRpc.Type.Genesis
7576
Cardano.Rpc.Server.Internal.UtxoRpc.Type.Governance
7677
Cardano.Rpc.Server.Internal.UtxoRpc.Type.PlutusData
@@ -81,10 +82,10 @@ library
8182
Cardano.Rpc.Server.Internal.UtxoRpc.Type.TxEval
8283
Cardano.Rpc.Server.Internal.UtxoRpc.Type.TxOutput
8384
Cardano.Rpc.Server.NodeKernelAccess
84-
Cardano.Rpc.Server.NodeKernelAccess.Type
8585

8686
other-modules:
8787
Cardano.Rpc.Server.Internal.Orphans
88+
Cardano.Rpc.Server.NodeKernelAccess.Internal.Type
8889
Paths_cardano_rpc
8990

9091
autogen-modules:
@@ -110,6 +111,7 @@ library
110111
cardano-ledger-dijkstra,
111112
cardano-ledger-shelley,
112113
cardano-rpc:gen,
114+
cardano-slotting,
113115
containers,
114116
contra-tracer,
115117
data-default,
@@ -125,10 +127,13 @@ library
125127
mempack,
126128
microlens,
127129
network,
130+
ouroboros-consensus,
131+
ouroboros-consensus:cardano,
128132
proto-lens >=0.7.1.7,
129133
proto-lens-protobuf-types,
130134
random,
131135
rio,
136+
sop-extras,
132137
strict-sop-core,
133138
text,
134139
time,
@@ -183,6 +188,7 @@ test-suite cardano-rpc-test
183188
cardano-ledger-shelley,
184189
cardano-ledger-shelley:testlib,
185190
cardano-rpc,
191+
cardano-slotting,
186192
containers,
187193
formatting,
188194
grpc-spec,
@@ -191,10 +197,12 @@ test-suite cardano-rpc-test
191197
hedgehog-quickcheck,
192198
memory,
193199
mtl,
200+
ouroboros-consensus,
194201
ouroboros-consensus:cardano,
195202
proto-lens,
196203
rio,
197204
scientific,
205+
sop-extras,
198206
tasty,
199207
tasty-hedgehog,
200208
text,
@@ -209,6 +217,7 @@ test-suite cardano-rpc-test
209217
build-tool-depends: tasty-discover:tasty-discover
210218
other-modules:
211219
Test.Cardano.Rpc.ByronTx
220+
Test.Cardano.Rpc.EraSummary
212221
Test.Cardano.Rpc.Eval
213222
Test.Cardano.Rpc.FetchBlockTx
214223
Test.Cardano.Rpc.FollowTipStream

cardano-rpc/src/Cardano/Rpc/Server.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ methodsUtxoRpc
7171
=> Methods m (ProtobufMethodsOf UtxoRpc.QueryService)
7272
methodsUtxoRpc =
7373
UnsupportedMethod -- readData
74-
. UnsupportedMethod -- readEraSummary
74+
. Method (mkNonStreaming $ wrapInSpan TraceRpcQueryReadEraSummarySpan . readEraSummaryMethod)
7575
. Method (mkNonStreaming $ wrapInSpan TraceRpcQueryReadGenesisSpan . readGenesisMethod)
7676
. Method (mkNonStreaming $ wrapInSpan TraceRpcQueryParamsSpan . readParamsMethod)
7777
. UnsupportedMethod -- readState

cardano-rpc/src/Cardano/Rpc/Server/Internal/Env.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ where
1010
import Cardano.Api
1111
import Cardano.Rpc.Server.Config
1212
import Cardano.Rpc.Server.Internal.Tracing
13-
import Cardano.Rpc.Server.NodeKernelAccess.Type (NodeKernelAccess)
13+
import Cardano.Rpc.Server.NodeKernelAccess.Internal.Type (NodeKernelAccess)
1414

1515
import Control.Tracer (Tracer)
1616
import Data.IORef

cardano-rpc/src/Cardano/Rpc/Server/Internal/Monad.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ where
2424
import Cardano.Api
2525
import Cardano.Rpc.Server.Internal.Env
2626
import Cardano.Rpc.Server.Internal.Tracing
27-
import Cardano.Rpc.Server.NodeKernelAccess.Type (NodeKernelAccess)
27+
import Cardano.Rpc.Server.NodeKernelAccess.Internal.Type (NodeKernelAccess)
2828

2929
import RIO
3030

cardano-rpc/src/Cardano/Rpc/Server/Internal/Tracing.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ data TraceRpcQuery
3737
TraceRpcQuerySearchUtxosSpan TraceSpanEvent
3838
| -- | Span trace marking ReadGenesis query
3939
TraceRpcQueryReadGenesisSpan TraceSpanEvent
40+
| -- | Span trace marking ReadEraSummary query
41+
TraceRpcQueryReadEraSummarySpan TraceSpanEvent
4042
deriving Show
4143

4244
instance Pretty TraceRpc where
@@ -70,6 +72,8 @@ instance Pretty TraceRpcQuery where
7072
TraceRpcQuerySearchUtxosSpan (SpanEnd _) -> "Finished query search UTXO method"
7173
TraceRpcQueryReadGenesisSpan (SpanBegin _) -> "Started query read genesis method"
7274
TraceRpcQueryReadGenesisSpan (SpanEnd _) -> "Finished query read genesis method"
75+
TraceRpcQueryReadEraSummarySpan (SpanBegin _) -> "Started query read era summary method"
76+
TraceRpcQueryReadEraSummarySpan (SpanEnd _) -> "Finished query read era summary method"
7377

7478
instance Error TraceRpcQuery where
7579
prettyError = pretty

cardano-rpc/src/Cardano/Rpc/Server/Internal/UtxoRpc/Query.hs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module Cardano.Rpc.Server.Internal.UtxoRpc.Query
1616
, readUtxosMethod
1717
, searchUtxosMethod
1818
, readGenesisMethod
19+
, readEraSummaryMethod
1920
, paginateByTxIn
2021
)
2122
where
@@ -201,14 +202,11 @@ readGenesisMethod
201202
-> m (Proto UtxoRpc.ReadGenesisResponse)
202203
readGenesisMethod _req = do
203204
-- TODO: field masks are ignored for now (same as readParamsMethod)
204-
NodeKernelAccess
205-
{ genesisConfig =
206-
genesisBundle@GenesisBundle
205+
nodeKernelAccess <- grabNodeKernelAccess
206+
let genesisBundle@GenesisBundle
207207
{ shelleyGenesisHash
208208
, shelleyGenesis = (shelleyGenesisFile, shelleyGenesisCache)
209-
}
210-
} <-
211-
grabNodeKernelAccess
209+
} = genesisConfig nodeKernelAccess
212210
shelleyGenesis <-
213211
readThroughCache shelleyGenesisCache $
214212
readShelleyGenesisWithInitialFunds shelleyGenesisFile shelleyGenesisHash
@@ -267,6 +265,21 @@ readShelleyGenesisWithInitialFunds shelleyGenesisFile@(File path) bootGenesisHas
267265
<> ": "
268266
<> Text.pack reason
269267

268+
-- | Handle the @ReadEraSummary@ RPC method.
269+
-- Returns the node's hard-fork era summary: one entry per era the node's
270+
-- ledger state has seen so far, with name and start/end boundaries. See
271+
-- 'eraSummariesToProto' for exactly which fields are populated.
272+
readEraSummaryMethod
273+
:: MonadRpc e m
274+
=> Proto UtxoRpc.ReadEraSummaryRequest
275+
-> m (Proto UtxoRpc.ReadEraSummaryResponse)
276+
readEraSummaryMethod _req = do
277+
-- TODO: field masks are ignored for now (same as readParamsMethod)
278+
nodeKernelAccess <- grabNodeKernelAccess
279+
summary <- readHardForkSummary nodeKernelAccess
280+
pure $
281+
defMessage & U5c.cardano .~ eraSummariesToProto (nodeKernelSystemStart nodeKernelAccess) summary
282+
270283
-- | The CAIP-2 chain identifier for a Cardano network, keyed on the Shelley
271284
-- network magic.
272285
-- This follows Dolos, the reference UTxO RPC implementation: the three

cardano-rpc/src/Cardano/Rpc/Server/Internal/UtxoRpc/Sync.hs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ fetchBlockMethod request = do
6666
<> tshow maxFetchBlockRefs
6767
<> "; batch your requests"
6868

69-
nodeKernelAccess@NodeKernelAccess{systemStart, readEraHistory} <- grabNodeKernelAccess
69+
nodeKernelAccess <- grabNodeKernelAccess
7070
blocks <- forM (request ^. U5c.ref) $ \blockRef -> do
7171
(slot, headerHash) <- blockRefToPoint blockRef
7272
let throwNotFound =
@@ -77,7 +77,8 @@ fetchBlockMethod request = do
7777
<> serialiseToRawBytesHexText headerHash
7878
(rawBytes, blockInMode) <-
7979
fetchBlock nodeKernelAccess slot headerHash >>= maybe throwNotFound pure
80-
timestamp <- slotTimestampOrThrow systemStart readEraHistory slot
80+
timestamp <-
81+
slotTimestampOrThrow (nodeKernelSystemStart nodeKernelAccess) (readEraHistory nodeKernelAccess) slot
8182
pure $ mkAnyChainBlock rawBytes blockInMode timestamp
8283
pure $ defMessage & U5c.block .~ blocks
8384

@@ -94,8 +95,11 @@ readTipMethod
9495
=> Proto U5c.ReadTipRequest
9596
-> m (Proto U5c.ReadTipResponse)
9697
readTipMethod _request = do
97-
NodeKernelAccess{chainDb, systemStart, readEraHistory} <- grabNodeKernelAccess
98-
tip <- readTipBlockRef chainDb (slotTimestampOrThrow systemStart readEraHistory)
98+
nodeKernelAccess <- grabNodeKernelAccess
99+
tip <-
100+
readTipBlockRef
101+
nodeKernelAccess
102+
(slotTimestampOrThrow (nodeKernelSystemStart nodeKernelAccess) (readEraHistory nodeKernelAccess))
99103
pure $ defMessage & U5c.maybe'tip .~ tip
100104

101105
-- | Handle the @FollowTip@ SyncService RPC method: stream fully parsed
@@ -115,7 +119,7 @@ readTipMethod _request = do
115119
-- slot and hash only, like ChainSync's @MsgRollBackward@. The tracked
116120
-- window is sized to the node's security parameter /k/, so no rollback
117121
-- consensus can produce falls outside it (see
118-
-- 'Cardano.Rpc.Server.NodeKernelAccess.Type.NodeKernelAccess').
122+
-- 'Cardano.Rpc.Server.NodeKernelAccess.securityParam').
119123
-- Every response also carries the current chain tip.
120124
--
121125
-- Errors: @INVALID_ARGUMENT@ if an intersection block ref has an invalid
@@ -131,28 +135,27 @@ followTipMethod
131135
-- ^ Callback used to send each streamed response
132136
-> m ()
133137
followTipMethod request send = do
134-
nodeKernelAccess@NodeKernelAccess{chainDb, systemStart, readEraHistory, securityParam} <-
135-
grabNodeKernelAccess
138+
nodeKernelAccess <- grabNodeKernelAccess
136139
requestedPoints <- traverse blockRefToIntersectPoint (request ^. U5c.intersect)
137140
withFollower nodeKernelAccess $ \follower -> do
138141
-- an empty intersect list follows from the current tip; resolving it
139142
-- reaches into ChainDB directly (there is no 'ChainFollower' operation
140143
-- for "the current tip point"), so this step stays here rather than
141144
-- moving into 'followTipStream', which only takes an already-resolved,
142145
-- non-empty point list
143-
let slotTimestamp = slotTimestampOrThrow systemStart readEraHistory
146+
let slotTimestamp = slotTimestampOrThrow (nodeKernelSystemStart nodeKernelAccess) (readEraHistory nodeKernelAccess)
144147
startPoints <-
145148
if null requestedPoints
146149
then do
147-
tipHeader <- liftIO $ Consensus.getTipHeader chainDb
150+
tipHeader <- readChainTipHeader nodeKernelAccess
148151
pure [maybe ChainPointAtGenesis tipHeaderPoint tipHeader]
149152
else pure requestedPoints
150153
followTipStream
151154
follower
152-
(readTipBlockRef chainDb slotTimestamp)
155+
(readTipBlockRef nodeKernelAccess slotTimestamp)
153156
slotTimestamp
154157
(fetchBlockByChainPoint nodeKernelAccess)
155-
(fromIntegral . L.unNonZero $ Consensus.maxRollbacks securityParam)
158+
(fromIntegral . L.unNonZero $ Consensus.maxRollbacks (securityParam nodeKernelAccess))
156159
send
157160
startPoints
158161

@@ -262,7 +265,7 @@ followTipStream
262265
-> Int
263266
-- ^ How many applied points to track for undo re-fetch. In production
264267
-- this is the node's security parameter /k/
265-
-- ('Cardano.Rpc.Server.NodeKernelAccess.Type.securityParam'). Consensus
268+
-- ('Cardano.Rpc.Server.NodeKernelAccess.securityParam'). Consensus
266269
-- never rolls back more than /k/ blocks, so tracking /k/ points covers
267270
-- every rollback the protocol can produce, on any network. An entry
268271
-- costs roughly 40 bytes, so the window costs about @40 * k@ bytes per
@@ -378,12 +381,12 @@ followTipStream ChainFollower{nextChange, findIntersect} readTip slotTimestamp f
378381
-- 'mkTipBlockRef', or 'Nothing' at origin.
379382
readTipBlockRef
380383
:: MonadIO m
381-
=> Consensus.ChainDB IO (Consensus.CardanoBlock Consensus.StandardCrypto)
384+
=> NodeKernelAccess
382385
-> (SlotNo -> m UTCTime)
383386
-- ^ Convert a slot to its wall-clock timestamp
384387
-> m (Maybe (Proto U5c.BlockRef))
385-
readTipBlockRef chainDb slotTimestamp = do
386-
tipHeader <- liftIO $ Consensus.getTipHeader chainDb
388+
readTipBlockRef nodeKernelAccess slotTimestamp = do
389+
tipHeader <- readChainTipHeader nodeKernelAccess
387390
forM tipHeader $ \header ->
388391
mkTipBlockRef header <$> slotTimestamp (Consensus.blockSlot header)
389392

@@ -396,8 +399,8 @@ slotTimestampOrThrow
396399
-- ^ Read current era history from the ledger state
397400
-> SlotNo
398401
-> m UTCTime
399-
slotTimestampOrThrow systemStart readEraHistory slot = do
400-
eraHistory <- readEraHistory
402+
slotTimestampOrThrow systemStart readEraHistoryAction slot = do
403+
eraHistory <- readEraHistoryAction
401404
slotToUTCTime systemStart eraHistory slot
402405
& either (const throwPastHorizon) pure
403406
where

cardano-rpc/src/Cardano/Rpc/Server/Internal/UtxoRpc/Type.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
module Cardano.Rpc.Server.Internal.UtxoRpc.Type
66
( utxoRpcPParamsToProtocolParams
77
, genesisBundleToProto
8+
, eraSummariesToProto
89
, utxoToUtxoRpcAnyUtxoData
910
, txInTxOutToAnyUtxoData
1011
, anyUtxoDataUtxoRpcToUtxo
@@ -31,6 +32,7 @@ where
3132

3233
import Cardano.Rpc.Server.Internal.UtxoRpc.Type.BigInt
3334
import Cardano.Rpc.Server.Internal.UtxoRpc.Type.ChainPoint
35+
import Cardano.Rpc.Server.Internal.UtxoRpc.Type.EraSummary
3436
import Cardano.Rpc.Server.Internal.UtxoRpc.Type.Genesis
3537
import Cardano.Rpc.Server.Internal.UtxoRpc.Type.PlutusData
3638
import Cardano.Rpc.Server.Internal.UtxoRpc.Type.ProtocolParameters

0 commit comments

Comments
 (0)