Skip to content

Commit 715d7ef

Browse files
authored
Merge pull request #888 from IntersectMBO/mgalazyn/feature/add-utxorpc-protocol-parameters-query
cardano-rpc | Add UTxO RPC protocol parameters query
2 parents f037d0d + 1c5da55 commit 715d7ef

File tree

11 files changed

+449
-16
lines changed

11 files changed

+449
-16
lines changed

cardano-rpc/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
(feature)
77
[PR 885](https://github.com/IntersectMBO/cardano-api/pull/885)
88

9+
- Add UTxO RPC protocol parameters query

cardano-rpc/cardano-rpc.cabal

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,25 +54,42 @@ library
5454
exposed-modules:
5555
Cardano.Rpc.Client
5656
Cardano.Rpc.Proto.Api.Node
57+
Cardano.Rpc.Proto.Api.UtxoRpc.Query
5758
Cardano.Rpc.Server
5859
Cardano.Rpc.Server.Config
5960
Cardano.Rpc.Server.Internal.Env
6061
Cardano.Rpc.Server.Internal.Error
6162
Cardano.Rpc.Server.Internal.Monad
63+
Cardano.Rpc.Server.Internal.UtxoRpc.Query
6264
Proto.Cardano.Rpc.Node
6365
Proto.Cardano.Rpc.Node_Fields
66+
Proto.Utxorpc.V1alpha.Cardano.Cardano
67+
Proto.Utxorpc.V1alpha.Cardano.Cardano_Fields
68+
Proto.Utxorpc.V1alpha.Query.Query
69+
Proto.Utxorpc.V1alpha.Query.Query_Fields
6470

6571
other-modules:
72+
Cardano.Rpc.Server.Internal.Orphans
6673
Paths_cardano_rpc
6774

6875
autogen-modules:
6976
Paths_cardano_rpc
7077
Proto.Cardano.Rpc.Node
7178
Proto.Cardano.Rpc.Node_Fields
79+
Proto.Utxorpc.V1alpha.Cardano.Cardano
80+
Proto.Utxorpc.V1alpha.Cardano.Cardano_Fields
81+
Proto.Utxorpc.V1alpha.Query.Query
82+
Proto.Utxorpc.V1alpha.Query.Query_Fields
7283

7384
build-depends:
7485
base,
86+
bytestring,
7587
cardano-api >=10.17,
88+
cardano-ledger-api,
89+
cardano-ledger-binary,
90+
cardano-ledger-conway,
91+
cardano-ledger-core,
92+
containers,
7693
contra-tracer,
7794
filepath,
7895
generic-data,

cardano-rpc/proto/cardano/rpc/node.proto

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
21
syntax = "proto3";
32

3+
package cardano.rpc;
4+
45
import "google/protobuf/empty.proto";
56

67
service Node {
@@ -10,7 +11,7 @@ service Node {
1011
}
1112

1213
enum Era {
13-
byron = 0;
14+
byron = 0;
1415
shelley = 1;
1516
allegra = 2;
1617
mary = 3;
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
syntax = "proto3";
2+
3+
package utxorpc.v1alpha.cardano;
4+
5+
// Represents a rational number as a fraction.
6+
message RationalNumber {
7+
int32 numerator = 1;
8+
uint32 denominator = 2;
9+
}
10+
11+
// PARAMS
12+
// ======
13+
14+
message ExUnits {
15+
uint64 steps = 1;
16+
uint64 memory = 2;
17+
}
18+
19+
message ExPrices {
20+
RationalNumber steps = 1;
21+
RationalNumber memory = 2;
22+
}
23+
24+
message ProtocolVersion {
25+
uint32 major = 1;
26+
uint32 minor = 2;
27+
}
28+
29+
message CostModel {
30+
repeated int64 values = 1;
31+
}
32+
33+
message CostModels {
34+
CostModel plutus_v1 = 1;
35+
CostModel plutus_v2 = 2;
36+
CostModel plutus_v3 = 3;
37+
}
38+
39+
message VotingThresholds {
40+
repeated RationalNumber thresholds = 1;
41+
}
42+
43+
message PParams {
44+
uint64 coins_per_utxo_byte = 1; // The number of coins per UTXO byte.
45+
uint64 max_tx_size = 2; // The maximum transaction size.
46+
uint64 min_fee_coefficient = 3; // The minimum fee coefficient.
47+
uint64 min_fee_constant = 4; // The minimum fee constant.
48+
uint64 max_block_body_size = 5; // The maximum block body size.
49+
uint64 max_block_header_size = 6; // The maximum block header size.
50+
uint64 stake_key_deposit = 7; // The stake key deposit.
51+
uint64 pool_deposit = 8; // The pool deposit.
52+
uint64 pool_retirement_epoch_bound = 9; // The pool retirement epoch bound.
53+
uint64 desired_number_of_pools = 10; // The desired number of pools.
54+
RationalNumber pool_influence = 11; // The pool influence.
55+
RationalNumber monetary_expansion = 12; // The monetary expansion.
56+
RationalNumber treasury_expansion = 13; // The treasury expansion.
57+
uint64 min_pool_cost = 14; // The minimum pool cost.
58+
ProtocolVersion protocol_version = 15; // The maximum value size in an output.
59+
uint64 max_value_size = 16; // The maximum value size.
60+
uint64 collateral_percentage = 17; // Percentage of the txfee which must be provided as collateral when including non-native scripts.
61+
uint64 max_collateral_inputs = 18; // The maximum collateral inputs.
62+
CostModels cost_models = 19; // The cost models.
63+
ExPrices prices = 20; // The prices.
64+
ExUnits max_execution_units_per_transaction = 21; // The maximum execution units per transaction.
65+
ExUnits max_execution_units_per_block = 22; // The maximum execution units per block.
66+
RationalNumber min_fee_script_ref_cost_per_byte = 23; // The minimum fee per script reference byte.
67+
VotingThresholds pool_voting_thresholds = 24; // The pool voting thresholds.
68+
VotingThresholds drep_voting_thresholds = 25; // The drep voting thresholds.
69+
uint32 min_committee_size = 26; // The minimum committee size.
70+
uint64 committee_term_limit = 27; // The committee term limit.
71+
uint64 governance_action_validity_period = 28; // The governance action validity period.
72+
uint64 governance_action_deposit = 29; // The governance action deposit.
73+
uint64 drep_deposit = 30; // The drep deposit.
74+
uint64 drep_inactivity_period = 31; // The drep inactivity period.
75+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/// A consistent view of the state of the ledger
2+
3+
syntax = "proto3";
4+
5+
package utxorpc.v1alpha.query;
6+
7+
import "google/protobuf/field_mask.proto";
8+
import "utxorpc/v1alpha/cardano/cardano.proto";
9+
10+
// Represents a specific point in the blockchain.
11+
message ChainPoint {
12+
uint64 slot = 1; // Slot number.
13+
bytes hash = 2; // Block hash.
14+
uint64 height = 3; // Block height.
15+
uint64 timestamp = 4; // Block ms timestamp
16+
}
17+
18+
// Request to get the chain parameters
19+
message ReadParamsRequest {
20+
google.protobuf.FieldMask field_mask = 1; // Field mask to selectively return fields in the parsed response.
21+
}
22+
23+
// An evenlope that holds parameter data from any of the compatible chains
24+
message AnyChainParams {
25+
oneof params {
26+
utxorpc.v1alpha.cardano.PParams cardano = 1; // Cardano parameters
27+
}
28+
}
29+
30+
// Response containing the chain parameters
31+
message ReadParamsResponse {
32+
AnyChainParams values = 1; // The value of the parameters.
33+
ChainPoint ledger_tip = 2; // The chain point that represent the ledger current position.
34+
}
35+
36+
// Service definition for querying the state of the chain.
37+
service QueryService {
38+
rpc ReadParams(ReadParamsRequest) returns (ReadParamsResponse); // Get overall chain state.
39+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ module Cardano.Rpc.Client
88
)
99
where
1010

11+
import Cardano.Rpc.Server.Internal.Orphans ()
12+
1113
import Data.ProtoLens.Field
1214
import Network.GRPC.Client
1315
import Network.GRPC.Client.StreamType.IO
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{-# LANGUAGE TypeFamilies #-}
2+
{-# OPTIONS_GHC -Wno-orphans #-}
3+
4+
module Cardano.Rpc.Proto.Api.UtxoRpc.Query
5+
( module Proto.Utxorpc.V1alpha.Query.Query
6+
, module Proto.Utxorpc.V1alpha.Query.Query_Fields
7+
, module Proto.Utxorpc.V1alpha.Cardano.Cardano
8+
, module Proto.Utxorpc.V1alpha.Cardano.Cardano_Fields
9+
)
10+
where
11+
12+
import Network.GRPC.Common
13+
import Network.GRPC.Common.Protobuf
14+
15+
import Proto.Utxorpc.V1alpha.Cardano.Cardano
16+
import Proto.Utxorpc.V1alpha.Cardano.Cardano_Fields hiding
17+
( values
18+
, vec'values
19+
)
20+
import Proto.Utxorpc.V1alpha.Query.Query
21+
import Proto.Utxorpc.V1alpha.Query.Query_Fields
22+
23+
type instance RequestMetadata (Protobuf QueryService meth) = NoMetadata
24+
25+
type instance ResponseInitialMetadata (Protobuf QueryService meth) = NoMetadata
26+
27+
type instance ResponseTrailingMetadata (Protobuf QueryService meth) = NoMetadata

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

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,20 @@ where
1616

1717
import Cardano.Api
1818
import Cardano.Rpc.Proto.Api.Node qualified as Rpc
19+
import Cardano.Rpc.Proto.Api.UtxoRpc.Query qualified as UtxoRpc
1920
import Cardano.Rpc.Server.Config
21+
import Cardano.Rpc.Server.Internal.Env
2022
import Cardano.Rpc.Server.Internal.Monad
23+
import Cardano.Rpc.Server.Internal.Orphans ()
24+
import Cardano.Rpc.Server.Internal.UtxoRpc.Query
2125

2226
import RIO
2327

2428
import Control.Tracer
2529
import Data.ProtoLens (defMessage)
2630
import Data.ProtoLens.Field (field)
2731
import Network.GRPC.Common
32+
import Network.GRPC.Server
2833
import Network.GRPC.Server.Protobuf
2934
import Network.GRPC.Server.Run
3035
import Network.GRPC.Server.StreamType
@@ -47,37 +52,59 @@ methodsNodeRpc
4752
=> Methods m (ProtobufMethodsOf Rpc.Node)
4853
methodsNodeRpc = Method (mkNonStreaming getEraMethod) NoMoreMethods
4954

55+
methodsUtxoRpc
56+
:: MonadRpc e m
57+
=> Methods m (ProtobufMethodsOf UtxoRpc.QueryService)
58+
methodsUtxoRpc =
59+
Method (mkNonStreaming readParamsMethod) NoMoreMethods
60+
5061
runRpcServer
5162
:: Tracer IO String
5263
-> IO (RpcConfig, NetworkMagic)
5364
-- ^ action which reloads RPC configuration
5465
-> IO ()
55-
runRpcServer tracer loadRpcConfig = handleExceptions $ do
56-
( RpcConfig
66+
runRpcServer tracer loadRpcConfig = handleFatalExceptions $ do
67+
( rpcConfig@RpcConfig
5768
{ isEnabled = Identity isEnabled
5869
, rpcSocketPath = Identity (File rpcSocketPathFp)
70+
, nodeSocketPath = Identity nodeSocketPath
5971
}
60-
, _networkMagic
72+
, networkMagic
6173
) <-
6274
loadRpcConfig
6375
let config =
6476
ServerConfig
6577
{ serverInsecure = Just $ InsecureUnix rpcSocketPathFp
6678
, serverSecure = Nothing
6779
}
80+
rpcEnv =
81+
RpcEnv
82+
{ config = rpcConfig
83+
, tracer = natTracer liftIO tracer
84+
, rpcLocalNodeConnectInfo = mkLocalNodeConnectInfo nodeSocketPath networkMagic
85+
}
6886

6987
-- TODO this is logged by node configuration already, so it would make sense to log it again when
7088
-- configuration gets reloaded
71-
-- putTrace $ "RPC configuration: " <> show rpcConfig
89+
-- traceWith $ "RPC configuration: " <> show rpcConfig
7290

7391
when isEnabled $
74-
runServerWithHandlers def config $
75-
mconcat
76-
[ fromMethods methodsNodeRpc
77-
]
92+
runRIO rpcEnv $
93+
withRunInIO $ \runInIO ->
94+
runServerWithHandlers serverParams config . fmap (hoistSomeRpcHandler runInIO) $
95+
mconcat
96+
[ fromMethods methodsNodeRpc
97+
, fromMethods methodsUtxoRpc
98+
]
7899
where
79-
handleExceptions :: (HasCallStack => IO ()) -> IO ()
80-
handleExceptions = handleAny $ \e ->
81-
putTrace $ "RPC server fatal error: " <> displayException e
100+
serverParams :: ServerParams
101+
serverParams = def{serverTopLevel = topLevelHandler}
102+
103+
-- Top level hook for request handlers, handle exceptions
104+
topLevelHandler :: RequestHandler () -> RequestHandler ()
105+
topLevelHandler h unmask req resp = catchAny (h unmask req resp) $ \e ->
106+
traceWith tracer $ "Exception when processing RPC request:\n" <> displayException e
82107

83-
putTrace = traceWith tracer
108+
handleFatalExceptions :: (HasCallStack => IO ()) -> IO ()
109+
handleFatalExceptions = handleAny $ \e ->
110+
traceWith tracer $ "RPC server fatal error: " <> displayException e

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

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,60 @@
22
{-# LANGUAGE DataKinds #-}
33
{-# LANGUAGE DerivingVia #-}
44
{-# LANGUAGE FlexibleContexts #-}
5+
{-# LANGUAGE FlexibleInstances #-}
56
{-# LANGUAGE GADTs #-}
67
{-# LANGUAGE MultiParamTypeClasses #-}
8+
{-# LANGUAGE NamedFieldPuns #-}
79
{-# LANGUAGE QuantifiedConstraints #-}
810
{-# LANGUAGE RankNTypes #-}
911
{-# LANGUAGE ScopedTypeVariables #-}
12+
{-# LANGUAGE TypeApplications #-}
1013

1114
module Cardano.Rpc.Server.Internal.Monad
12-
( MonadRpc
15+
( Has (..)
16+
, MonadRpc
17+
, grab
18+
, putTrace
1319
)
1420
where
1521

1622
import Cardano.Api
23+
import Cardano.Rpc.Server.Internal.Env
1724

1825
import RIO
1926

20-
type MonadRpc e m = (HasCallStack, MonadIO m)
27+
import Control.Tracer (Tracer, traceWith)
28+
29+
-- | Provides a value of type 'field' from the value 'env'
30+
-- Used in conjunction with 'MonadReader env m' allows to easily access fields from the environment.
31+
class Has field env where
32+
obtain :: env -> field
33+
34+
instance Has a a where
35+
obtain = id
36+
37+
instance Has LocalNodeConnectInfo RpcEnv where
38+
obtain RpcEnv{rpcLocalNodeConnectInfo} = rpcLocalNodeConnectInfo
39+
40+
instance MonadIO m => Has (Tracer m String) RpcEnv where
41+
obtain RpcEnv{tracer} = tracer
42+
43+
-- | Obtain the field from the environment
44+
grab
45+
:: forall field env m
46+
. (Has field env, MonadReader env m)
47+
=> m field
48+
grab = asks $ obtain @field
49+
{-# INLINE grab #-}
50+
51+
-- | Using tracer from the environment, print the trace
52+
putTrace :: (Has (Tracer m t) e, MonadReader e m) => t -> m ()
53+
putTrace t = grab >>= (`traceWith` t)
54+
55+
type MonadRpc e m =
56+
( Has (Tracer m String) e
57+
, Has LocalNodeConnectInfo e
58+
, HasCallStack
59+
, MonadReader e m
60+
, MonadUnliftIO m
61+
)

0 commit comments

Comments
 (0)