@@ -3,20 +3,22 @@ package api
33import (
44 "encoding/hex"
55 "fmt"
6+ "io"
7+ "time"
8+
69 "github.com/cloudstruct/go-cardano-ledger"
710 "github.com/cloudstruct/go-cardano-submit-api/internal/config"
811 "github.com/cloudstruct/go-cardano-submit-api/internal/logging"
912 ouroboros "github.com/cloudstruct/go-ouroboros-network"
1013 "github.com/cloudstruct/go-ouroboros-network/protocol/localtxsubmission"
14+
1115 "github.com/fxamacker/cbor/v2"
1216 ginzap "github.com/gin-contrib/zap"
1317 "github.com/gin-gonic/gin"
1418 "github.com/penglongli/gin-metrics/ginmetrics"
1519 swaggerFiles "github.com/swaggo/files" // swagger embed files
1620 ginSwagger "github.com/swaggo/gin-swagger" // gin-swagger middleware
1721 "golang.org/x/crypto/blake2b"
18- "io"
19- "time"
2022
2123 _ "github.com/cloudstruct/go-cardano-submit-api/docs" // docs is generated by Swag CLI
2224)
@@ -172,19 +174,16 @@ func handleSubmitTx(c *gin.Context) {
172174 txIdHex := hex .EncodeToString (txIdHash [:])
173175 // Connect to cardano-node and submit TX
174176 errorChan := make (chan error )
175- doneChan := make (chan bool )
176- oOpts := & ouroboros.OuroborosOptions {
177- NetworkMagic : uint32 (cfg .Node .NetworkMagic ),
178- ErrorChan : errorChan ,
179- UseNodeToNodeProtocol : false ,
180- }
181- oConn , err := ouroboros .New (oOpts )
182- defer func () {
183- // We have to close the channel to break out of the async error handler goroutine
184- close (errorChan )
185- // Close Ouroboros connection
186- oConn .Close ()
187- }()
177+ oConn , err := ouroboros .New (
178+ ouroboros .WithNetworkMagic (uint32 (cfg .Node .NetworkMagic )),
179+ ouroboros .WithErrorChan (errorChan ),
180+ ouroboros .WithNodeToNode (false ),
181+ ouroboros .WithLocalTxSubmissionConfig (
182+ localtxsubmission .NewConfig (
183+ localtxsubmission .WithTimeout (5 * time .Second ),
184+ ),
185+ ),
186+ )
188187 if err != nil {
189188 logger .Errorf ("failure creating Ouroboros connection: %s" , err )
190189 c .JSON (500 , "failure communicating with node" )
@@ -213,50 +212,36 @@ func handleSubmitTx(c *gin.Context) {
213212 logger .Errorf ("failure communicating with node: %s" , err )
214213 c .JSON (500 , "failure communicating with node" )
215214 _ = ginmetrics .GetMonitor ().GetMetric ("tx_submit_fail_count" ).Inc (nil )
216- doneChan <- true
217215 }
218216 }()
217+ defer func () {
218+ // Close Ouroboros connection
219+ oConn .Close ()
220+ }()
219221 // Start local-tx-submission protocol
220- localTxSubmissionCallbackConfig := & localtxsubmission.CallbackConfig {
221- AcceptTxFunc : func () error {
222- // Return transaction ID
223- c .JSON (202 , txIdHex )
224- doneChan <- true
225- // Increment custom metric
226- _ = ginmetrics .GetMonitor ().GetMetric ("tx_submit_count" ).Inc (nil )
227- return nil
228- },
229- RejectTxFunc : func (reasonCbor []byte ) error {
230- if c .GetHeader ("Accept" ) == "application/cbor" {
231- c .Data (400 , "application/cbor" , reasonCbor )
232- } else {
233- if reason , err := ledger .NewTxSubmitErrorFromCbor (reasonCbor ); err == nil {
234- c .JSON (400 , reason )
235- } else {
236- c .JSON (400 , fmt .Sprintf ("transaction rejected by node, but the 'reason' data could not be parsed (raw CBOR: %x)" , reasonCbor ))
237- }
238- }
239- doneChan <- true
240- // Increment custom metric
241- _ = ginmetrics .GetMonitor ().GetMetric ("tx_submit_fail_count" ).Inc (nil )
242- return nil
243- },
244- }
245- oConn .LocalTxSubmission .Start (localTxSubmissionCallbackConfig )
222+ oConn .LocalTxSubmission ().Client .Start ()
246223 // Determine transaction type (era)
247224 txType , err := determineTransactionType (txRawBytes )
248225 if err != nil {
249226 c .JSON (400 , "could not parse transaction to determine type" )
250227 return
251228 }
252229 // Submit the transaction
253- if err := oConn .LocalTxSubmission .SubmitTx (txType , txRawBytes ); err != nil {
254- logger .Errorf ("failure submitting transaction: %s" , err )
255- c .JSON (500 , "failure communicating with node" )
230+ if err := oConn .LocalTxSubmission ().Client .SubmitTx (txType , txRawBytes ); err != nil {
231+ if c .GetHeader ("Accept" ) == "application/cbor" {
232+ txRejectErr := err .(localtxsubmission.TransactionRejectedError )
233+ c .Data (400 , "application/cbor" , txRejectErr .ReasonCbor )
234+ } else {
235+ c .JSON (400 , err .Error ())
236+ }
237+ // Increment custom metric
238+ _ = ginmetrics .GetMonitor ().GetMetric ("tx_submit_fail_count" ).Inc (nil )
256239 return
257240 }
258- // Wait for async process to finish
259- <- doneChan
241+ // Return transaction ID
242+ c .JSON (202 , txIdHex )
243+ // Increment custom metric
244+ _ = ginmetrics .GetMonitor ().GetMetric ("tx_submit_count" ).Inc (nil )
260245}
261246
262247func determineTransactionType (data []byte ) (uint16 , error ) {
0 commit comments