Skip to content

Commit db70b89

Browse files
committed
cardano-rpc | Add UTxO RPC: submitTx method
1 parent 7f85366 commit db70b89

File tree

5 files changed

+130
-1
lines changed

5 files changed

+130
-1
lines changed

cardano-rpc/cardano-rpc.cabal

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,19 +55,23 @@ library
5555
Cardano.Rpc.Client
5656
Cardano.Rpc.Proto.Api.Node
5757
Cardano.Rpc.Proto.Api.UtxoRpc.Query
58+
Cardano.Rpc.Proto.Api.UtxoRpc.Submit
5859
Cardano.Rpc.Server
5960
Cardano.Rpc.Server.Config
6061
Cardano.Rpc.Server.Internal.Env
6162
Cardano.Rpc.Server.Internal.Error
6263
Cardano.Rpc.Server.Internal.Monad
6364
Cardano.Rpc.Server.Internal.UtxoRpc.Query
6465
Cardano.Rpc.Server.Internal.UtxoRpc.Type
66+
Cardano.Rpc.Server.Internal.UtxoRpc.Submit
6567
Proto.Cardano.Rpc.Node
6668
Proto.Cardano.Rpc.Node_Fields
6769
Proto.Utxorpc.V1alpha.Cardano.Cardano
6870
Proto.Utxorpc.V1alpha.Cardano.Cardano_Fields
6971
Proto.Utxorpc.V1alpha.Query.Query
7072
Proto.Utxorpc.V1alpha.Query.Query_Fields
73+
Proto.Utxorpc.V1alpha.Submit.Submit
74+
Proto.Utxorpc.V1alpha.Submit.Submit_Fields
7175

7276
other-modules:
7377
Cardano.Rpc.Server.Internal.Orphans
@@ -81,6 +85,8 @@ library
8185
Proto.Utxorpc.V1alpha.Cardano.Cardano_Fields
8286
Proto.Utxorpc.V1alpha.Query.Query
8387
Proto.Utxorpc.V1alpha.Query.Query_Fields
88+
Proto.Utxorpc.V1alpha.Submit.Submit
89+
Proto.Utxorpc.V1alpha.Submit.Submit_Fields
8490

8591
build-depends:
8692
base,

cardano-rpc/proto/utxorpc/v1alpha/submit/submit.proto

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,18 @@ message SubmitTxRequest {
1414
repeated AnyChainTx tx = 1; // List of transactions to submit.
1515
}
1616

17+
// TODO u5c: new type
18+
message TxSubmitResult {
19+
oneof result {
20+
bytes ref = 1; // Transaction references.
21+
string error_message = 2; // The error message
22+
}
23+
}
24+
1725
// Response containing references to the submitted transactions.
26+
// TODO u5c: changed type
1827
message SubmitTxResponse {
19-
repeated bytes ref = 1; // List of transaction references.
28+
repeated TxSubmitResult results = 1; // List of either transaction references or error messages.
2029
}
2130

2231
// Service definition for submitting transactions and checking their status.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{-# LANGUAGE TypeFamilies #-}
2+
{-# OPTIONS_GHC -Wno-orphans #-}
3+
4+
module Cardano.Rpc.Proto.Api.UtxoRpc.Submit
5+
( module Proto.Utxorpc.V1alpha.Submit.Submit
6+
, module Proto.Utxorpc.V1alpha.Submit.Submit_Fields
7+
)
8+
where
9+
10+
import Network.GRPC.Common
11+
import Network.GRPC.Common.Protobuf
12+
13+
import Proto.Utxorpc.V1alpha.Submit.Submit
14+
import Proto.Utxorpc.V1alpha.Submit.Submit_Fields
15+
16+
type instance RequestMetadata (Protobuf SubmitService meth) = NoMetadata
17+
18+
type instance ResponseInitialMetadata (Protobuf SubmitService meth) = NoMetadata
19+
20+
type instance ResponseTrailingMetadata (Protobuf SubmitService meth) = NoMetadata

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@ where
1717
import Cardano.Api
1818
import Cardano.Rpc.Proto.Api.Node qualified as Rpc
1919
import Cardano.Rpc.Proto.Api.UtxoRpc.Query qualified as UtxoRpc
20+
import Cardano.Rpc.Proto.Api.UtxoRpc.Submit qualified as UtxoRpc
2021
import Cardano.Rpc.Server.Config
2122
import Cardano.Rpc.Server.Internal.Env
2223
import Cardano.Rpc.Server.Internal.Monad
2324
import Cardano.Rpc.Server.Internal.Orphans ()
2425
import Cardano.Rpc.Server.Internal.UtxoRpc.Query
26+
import Cardano.Rpc.Server.Internal.UtxoRpc.Submit
2527

2628
import RIO
2729

@@ -60,6 +62,12 @@ methodsUtxoRpc =
6062
. Method (mkNonStreaming readUtxosMethod)
6163
$ NoMoreMethods
6264

65+
methodsUtxoRpcSubmit
66+
:: MonadRpc e m
67+
=> Methods m (ProtobufMethodsOf UtxoRpc.SubmitService)
68+
methodsUtxoRpcSubmit =
69+
Method (mkNonStreaming submitTxMethod) NoMoreMethods
70+
6371
runRpcServer
6472
:: Tracer IO String
6573
-> IO (RpcConfig, NetworkMagic)
@@ -97,6 +105,7 @@ runRpcServer tracer loadRpcConfig = handleFatalExceptions $ do
97105
mconcat
98106
[ fromMethods methodsNodeRpc
99107
, fromMethods methodsUtxoRpc
108+
, fromMethods methodsUtxoRpcSubmit
100109
]
101110
where
102111
serverParams :: ServerParams
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
{-# LANGUAGE ConstraintKinds #-}
2+
{-# LANGUAGE DataKinds #-}
3+
{-# LANGUAGE DerivingVia #-}
4+
{-# LANGUAGE FlexibleContexts #-}
5+
{-# LANGUAGE GADTs #-}
6+
{-# LANGUAGE LambdaCase #-}
7+
{-# LANGUAGE OverloadedLabels #-}
8+
{-# LANGUAGE QuantifiedConstraints #-}
9+
{-# LANGUAGE RankNTypes #-}
10+
{-# LANGUAGE TypeApplications #-}
11+
12+
module Cardano.Rpc.Server.Internal.UtxoRpc.Submit
13+
( submitTxMethod
14+
)
15+
where
16+
17+
import Cardano.Api
18+
import Cardano.Api.Network.IPC qualified as Net.Tx
19+
import Cardano.Rpc.Proto.Api.UtxoRpc.Submit qualified as UtxoRpc
20+
import Cardano.Rpc.Server.Internal.Error
21+
import Cardano.Rpc.Server.Internal.Monad
22+
import Cardano.Rpc.Server.Internal.Orphans ()
23+
24+
import RIO hiding (toList)
25+
26+
import Data.Default
27+
import Network.GRPC.Spec
28+
29+
-- | Submit a CBOR-serialised list of transactions to the node
30+
submitTxMethod
31+
:: MonadRpc e m
32+
=> Proto UtxoRpc.SubmitTxRequest
33+
-> m (Proto UtxoRpc.SubmitTxResponse)
34+
-- ^ A list of succeeded transaction ids or errors for failed ones
35+
submitTxMethod req = do
36+
-- index transactions in the request
37+
let serialisedTxs = zip @Int [0 ..] $ req ^.. #tx . traverse . #raw
38+
39+
nodeConnInfo <- grab
40+
AnyCardanoEra era <- liftIO . throwExceptT $ determineEra nodeConnInfo
41+
eon <- forEraInEon era (error "Minimum Shelley era required") pure
42+
43+
-- try to submit each one consecutively
44+
submitResults <- forM serialisedTxs $ \(i, txBytes) -> do
45+
let eTx =
46+
first (("Failed to decode transaction with index " <> show i <> ": ") <>) $
47+
deserialiseTx eon txBytes
48+
49+
eTxId <-
50+
fmap join . forM eTx $
51+
fmap
52+
( first
53+
( ("Failed to submit transaction with index " <> show i <> ": ")
54+
<>
55+
)
56+
)
57+
. submitTx eon
58+
59+
pure $ case eTxId of
60+
Left err -> def & #errorMessage .~ fromString err
61+
Right txId' -> def & #ref .~ serialiseToRawBytes txId'
62+
63+
pure $ def & #results .~ submitResults
64+
where
65+
deserialiseTx :: ShelleyBasedEra era -> ByteString -> Either String (Tx era)
66+
deserialiseTx sbe = shelleyBasedEraConstraints sbe $ first show . deserialiseFromCBOR asType
67+
68+
submitTx
69+
:: MonadRpc e m
70+
=> ShelleyBasedEra era
71+
-> Tx era
72+
-> m (Either String TxId)
73+
submitTx sbe tx = do
74+
nodeConnInfo <- grab
75+
eRes <-
76+
tryAny $
77+
submitTxToNodeLocal nodeConnInfo (TxInMode sbe tx) >>= \case
78+
Net.Tx.SubmitFail reason -> pure . Left $ show reason
79+
Net.Tx.SubmitSuccess -> pure $ Right . getTxId $ getTxBody tx
80+
case eRes of
81+
Left err -> do
82+
let errString = displayException err
83+
putTrace $ "N2C connection error while trying to submit a transaction: " <> errString
84+
pure $ Left errString
85+
Right res -> pure res

0 commit comments

Comments
 (0)