Skip to content

Commit d3ed91c

Browse files
authored
Merge pull request #1259 from IntersectMBO/mgalazyn/reature/read-tip
cardano-rpc: ReadTip
2 parents eb8491a + b833c44 commit d3ed91c

8 files changed

Lines changed: 67 additions & 4 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
project: cardano-api
2+
pr: 1259
3+
kind:
4+
- compatible
5+
description: |
6+
Re-export getTipHeader, blockHash and blockSlot from Cardano.Api.Consensus.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
project: cardano-rpc
2+
pr: 1259
3+
kind:
4+
- feature
5+
description: |
6+
Implement the ReadTip SyncService method: returns the current chain tip as slot, block hash, height and timestamp.

cardano-api/src/Cardano/Api/Consensus.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ module Cardano.Api.Consensus
5454
, ChainDB.ChainDB
5555
, ChainDB.getBlockComponent
5656
, ChainDB.getCurrentLedger
57+
, ChainDB.getTipHeader
5758
, ConfigSupportsNode
5859
, ChainDepState
5960
, GenTx (..)
@@ -71,7 +72,9 @@ module Cardano.Api.Consensus
7172
, StandardCrypto
7273
, TopLevelConfig
7374
, ledgerState
75+
, blockHash
7476
, blockNo
77+
, blockSlot
7578
, byronBlockRaw
7679
, byronIdTx
7780
, configBlock

cardano-api/src/Cardano/Api/Consensus/Internal/Reexport.hs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ module Cardano.Api.Consensus.Internal.Reexport
1919
, StandardCrypto
2020
, TopLevelConfig
2121
, ledgerState
22+
, blockHash
2223
, blockNo
24+
, blockSlot
2325
, byronBlockRaw
2426
, byronIdTx
2527
, configBlock
@@ -34,7 +36,14 @@ module Cardano.Api.Consensus.Internal.Reexport
3436
where
3537

3638
import Cardano.Protocol.Crypto (StandardCrypto)
37-
import Ouroboros.Consensus.Block (HasHeader, HeaderHash, RealPoint (..), blockNo)
39+
import Ouroboros.Consensus.Block
40+
( HasHeader
41+
, HeaderHash
42+
, RealPoint (..)
43+
, blockHash
44+
, blockNo
45+
, blockSlot
46+
)
3847
import Ouroboros.Consensus.Byron.Ledger (ByronBlock (byronBlockRaw), GenTx (..), byronIdTx)
3948
import Ouroboros.Consensus.Cardano.Block (CardanoBlock, EraMismatch (..))
4049
import Ouroboros.Consensus.Config (TopLevelConfig, configBlock, configLedger)

cardano-rpc/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ It implements [UTxO RPC](https://utxorpc.org/introduction) protobuf communicatio
3636
| [FetchBlock](https://utxorpc.org/sync/spec/#fetchblockrequest) | ✅ Supported |
3737
| [DumpHistory](https://utxorpc.org/sync/spec/#dumphistoryrequest) | ⬜ Not supported |
3838
| [FollowTip](https://utxorpc.org/sync/spec/#followtiprequest) | ⬜ Not supported |
39-
| [ReadTip](https://utxorpc.org/sync/spec/#readtiprequest) | ⬜ Not supported |
39+
| [ReadTip](https://utxorpc.org/sync/spec/#readtiprequest) | ✅ Supported |
4040

4141
### [WatchService](https://utxorpc.org/watch/spec/)
4242

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ methodsSyncRpc =
8585
Method (mkNonStreaming $ const unimplemented) -- dumpHistory
8686
. Method (mkNonStreaming $ wrapInSpan TraceRpcFetchBlockSpan . fetchBlockMethod)
8787
. Method (mkServerStreaming $ \_ _ -> unimplemented) -- followTip
88-
. Method (mkNonStreaming $ const unimplemented) -- readTip
88+
. Method (mkNonStreaming $ wrapInSpan TraceRpcReadTipSpan . readTipMethod)
8989
$ NoMoreMethods
9090
where
9191
unimplemented =

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,12 @@ instance Pretty TraceRpcSubmit where
9595
instance Error TraceRpcSubmit where
9696
prettyError = pretty
9797

98-
-- | Traces used in SyncService (FetchBlock, FollowTip)
98+
-- | Traces used in SyncService (FetchBlock, ReadTip, FollowTip)
9999
data TraceRpcSync
100100
= -- | FetchBlock span
101101
TraceRpcFetchBlockSpan TraceSpanEvent
102+
| -- | ReadTip span
103+
TraceRpcReadTipSpan TraceSpanEvent
102104
| -- | Requested block was not found
103105
TraceRpcFetchBlockNotFound SlotNo
104106
| -- | Node kernel access is not yet available
@@ -111,6 +113,8 @@ instance Pretty TraceRpcSync where
111113
pretty = \case
112114
TraceRpcFetchBlockSpan (SpanBegin _) -> "Started FetchBlock method"
113115
TraceRpcFetchBlockSpan (SpanEnd _) -> "Finished FetchBlock method"
116+
TraceRpcReadTipSpan (SpanBegin _) -> "Started ReadTip method"
117+
TraceRpcReadTipSpan (SpanEnd _) -> "Finished ReadTip method"
114118
TraceRpcFetchBlockNotFound slot -> "Block not found at slot " <> pshow slot
115119
TraceRpcNodeKernelAccessUnavailable -> "Node kernel access not yet initialised"
116120
TraceRpcForkerError e -> "Ledger forker error: " <> pretty e

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
-- (fetching blocks, dumping history, following the tip).
99
module Cardano.Rpc.Server.Internal.UtxoRpc.Sync
1010
( fetchBlockMethod
11+
, readTipMethod
1112
)
1213
where
1314

1415
import Cardano.Api
16+
import Cardano.Api.Consensus qualified as Consensus
1517
import Cardano.Rpc.Proto.Api.UtxoRpc.Sync qualified as U5c
1618
import Cardano.Rpc.Server.Internal.Error
1719
import Cardano.Rpc.Server.Internal.Monad
@@ -23,6 +25,7 @@ import Cardano.Rpc.Server.NodeKernelAccess
2325
import RIO
2426

2527
import Data.ByteString qualified as BS
28+
import Data.ByteString.Short qualified as SBS
2629
import Data.ProtoLens (defMessage)
2730
import Data.Time.Clock.POSIX (utcTimeToPOSIXSeconds)
2831
import Network.GRPC.Spec (GrpcError (GrpcInternal, GrpcInvalidArgument, GrpcNotFound), Proto)
@@ -88,3 +91,35 @@ fetchBlockMethod request = do
8891
& U5c.cardano . U5c.body . U5c.tx .~ txs
8992
& U5c.cardano . U5c.timestamp .~ timestampMs
9093
)
94+
95+
-- | Handle the @ReadTip@ SyncService RPC method.
96+
-- Reads the current chain tip from ChainDB and returns it as slot, block
97+
-- header hash, block height and slot timestamp.
98+
-- When the chain is at origin, the tip field is left unset.
99+
readTipMethod
100+
:: MonadRpc e m
101+
=> Proto U5c.ReadTipRequest
102+
-> m (Proto U5c.ReadTipResponse)
103+
readTipMethod _request = do
104+
NodeKernelAccess{chainDb, systemStart, readEraHistory} <- grabNodeKernelAccess
105+
tipHeader <- liftIO $ Consensus.getTipHeader chainDb
106+
tip <- forM tipHeader $ \header -> do
107+
let slot = Consensus.blockSlot header
108+
Consensus.OneEraHash tipHash = Consensus.blockHash header
109+
BlockNo height = Consensus.blockNo header
110+
throwPastHorizon =
111+
throwGrpcErrorWithMessage GrpcInternal $
112+
"cannot convert tip slot "
113+
<> tshow (unSlotNo slot)
114+
<> " to timestamp: the slot is past the era history horizon"
115+
eraHistory <- readEraHistory
116+
timestampMs <-
117+
slotToUTCTime systemStart eraHistory slot
118+
& either (const throwPastHorizon) (pure . round . (* 1000) . utcTimeToPOSIXSeconds)
119+
pure $
120+
defMessage
121+
& U5c.slot .~ unSlotNo slot
122+
& U5c.hash .~ SBS.fromShort tipHash
123+
& U5c.height .~ height
124+
& U5c.timestamp .~ timestampMs
125+
pure $ defMessage & U5c.maybe'tip .~ tip

0 commit comments

Comments
 (0)