From ce9a0417fd99b064ddabe1b2ae28c6d039780a18 Mon Sep 17 00:00:00 2001 From: Gui Iribarren Date: Wed, 4 Sep 2024 11:37:18 +0200 Subject: [PATCH 1/3] api: new endpoint /chain/transactions/{hash} * mark /chain/transactions/{height}/{index} as @Deprecated --- api/chain.go | 52 +++++++++++++++++++++++++++++++--- vochain/indexer/transaction.go | 12 ++++++++ 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/api/chain.go b/api/chain.go index d10865664..759d9e8a5 100644 --- a/api/chain.go +++ b/api/chain.go @@ -116,7 +116,7 @@ func (a *API) enableChainHandlers() error { "/chain/transactions/{height}/{index}", "GET", apirest.MethodAccessTypePublic, - a.chainTxHandler, + a.chainTxByHeightAndIndexHandler, ); err != nil { return err } @@ -136,6 +136,14 @@ func (a *API) enableChainHandlers() error { ); err != nil { return err } + if err := a.Endpoint.RegisterMethod( + "/chain/transactions/{hash}", + "GET", + apirest.MethodAccessTypePublic, + a.chainTxByHashHandler, + ); err != nil { + return err + } if err := a.Endpoint.RegisterMethod( "/chain/transactions/page/{page}", "GET", @@ -639,7 +647,7 @@ func (a *API) chainTxCostHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext // @Success 204 "See [errors](vocdoni-api#errors) section" // @Router /chain/transactions/reference/{hash} [get] func (a *API) chainTxRefByHashHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error { - hash, err := hex.DecodeString(util.TrimHex(ctx.URLParam("hash"))) + hash, err := hex.DecodeString(util.TrimHex(ctx.URLParam(ParamHash))) if err != nil { return err } @@ -658,10 +666,12 @@ func (a *API) chainTxRefByHashHandler(_ *apirest.APIdata, ctx *httprouter.HTTPCo return ctx.Send(data, apirest.HTTPstatusOK) } -// chainTxHandler +// chainTxByHeightAndIndexHandler // // @Summary Transaction by block height and index // @Description Get transaction full information by block height and index. It returns JSON transaction protobuf encoded. Depending of transaction type will return different types of objects. Current transaction types can be found calling `/chain/transactions/cost` +// @Deprecated +// @Description (deprecated, in favor of /chain/transactions/{hash}) // @Tags Chain // @Accept json // @Produce json @@ -670,7 +680,7 @@ func (a *API) chainTxRefByHashHandler(_ *apirest.APIdata, ctx *httprouter.HTTPCo // @Success 200 {object} GenericTransactionWithInfo // @Success 204 "See [errors](vocdoni-api#errors) section" // @Router /chain/transactions/{height}/{index} [get] -func (a *API) chainTxHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error { +func (a *API) chainTxByHeightAndIndexHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error { height, err := strconv.ParseInt(ctx.URLParam(ParamHeight), 10, 64) if err != nil { return err @@ -697,6 +707,40 @@ func (a *API) chainTxHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) er return ctx.Send(data, apirest.HTTPstatusOK) } +// chainTxByHashHandler +// +// @Summary Transaction by hash +// @Description Get transaction full information by hash. It returns JSON transaction protobuf encoded. Depending of transaction type will return different types of objects. Current transaction types can be found calling `/chain/transactions/cost` +// @Tags Chain +// @Accept json +// @Produce json +// @Param hash path string true "Transaction hash" +// @Success 200 {object} GenericTransactionWithInfo +// @Success 204 "See [errors](vocdoni-api#errors) section" +// @Router /chain/transactions/{hash} [get] +func (a *API) chainTxByHashHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error { + hash, err := hex.DecodeString(util.TrimHex(ctx.URLParam(ParamHash))) + if err != nil { + return ErrCantParseHexString.WithErr(err) + } + ref, err := a.indexer.GetTransactionByHash(hash) + if err != nil { + if errors.Is(err, indexer.ErrTransactionNotFound) { + return ErrTransactionNotFound + } + return ErrVochainGetTxFailed.WithErr(err) + } + tx := &GenericTransactionWithInfo{ + TxContent: protoTxAsJSON(ref.RawTx), + TxInfo: ref, + } + data, err := json.Marshal(tx) + if err != nil { + return err + } + return ctx.Send(data, apirest.HTTPstatusOK) +} + // chainTxListHandler // // @Summary List transactions diff --git a/vochain/indexer/transaction.go b/vochain/indexer/transaction.go index 31beb4465..41a6a1818 100644 --- a/vochain/indexer/transaction.go +++ b/vochain/indexer/transaction.go @@ -42,6 +42,18 @@ func (idx *Indexer) GetTxMetadataByHash(hash types.HexBytes) (*indexertypes.Tran return indexertypes.TransactionMetadataFromDB(&sqlTxRef), nil } +// GetTransactionByHash fetches the full tx for the given tx hash +func (idx *Indexer) GetTransactionByHash(hash types.HexBytes) (*indexertypes.Transaction, error) { + sqlTxRef, err := idx.readOnlyQuery.GetTransactionByHash(context.TODO(), hash) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil, ErrTransactionNotFound + } + return nil, fmt.Errorf("tx hash %x not found: %v", hash, err) + } + return indexertypes.TransactionFromDB(&sqlTxRef), nil +} + // GetTransactionByHeightAndIndex fetches the full tx for the given tx height and block tx index func (idx *Indexer) GetTransactionByHeightAndIndex(blockHeight, blockIndex int64) (*indexertypes.Transaction, error) { sqlTxRef, err := idx.readOnlyQuery.GetTransactionByHeightAndIndex(context.TODO(), indexerdb.GetTransactionByHeightAndIndexParams{ From 8e5c29b33da9021d7ede02606df08cc67bb7f548 Mon Sep 17 00:00:00 2001 From: Gui Iribarren Date: Wed, 4 Sep 2024 12:26:59 +0200 Subject: [PATCH 2/3] fixup! api: fetch blocks and transactions from indexer rather than app BlockStore --- api/api_types.go | 1 + 1 file changed, 1 insertion(+) diff --git a/api/api_types.go b/api/api_types.go index 982e3c9d1..26b13508e 100644 --- a/api/api_types.go +++ b/api/api_types.go @@ -297,6 +297,7 @@ type TransfersList struct { type GenericTransactionWithInfo struct { TxContent json.RawMessage `json:"tx"` TxInfo *indexertypes.Transaction `json:"txInfo"` + Signature types.HexBytes `json:"signature"` } type ChainInfo struct { From 5c9a04510061a1701aa5318ce9dc91ec21794d2a Mon Sep 17 00:00:00 2001 From: Gui Iribarren Date: Wed, 4 Sep 2024 13:02:22 +0200 Subject: [PATCH 3/3] fixup! indexer: index more details about blocks and transactions --- vochain/indexer/indexertypes/types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vochain/indexer/indexertypes/types.go b/vochain/indexer/indexertypes/types.go index 7e54e25a7..ad5b29748 100644 --- a/vochain/indexer/indexertypes/types.go +++ b/vochain/indexer/indexertypes/types.go @@ -212,7 +212,7 @@ func TransactionMetadataFromDBRow(dbtx *indexerdb.SearchTransactionsRow) *Transa type Transaction struct { *TransactionMetadata RawTx types.HexBytes `json:"-"` - Signature types.HexBytes `json:"signature,omitempty"` + Signature types.HexBytes `json:"-"` } // TransactionFromDB converts an indexerdb.Transaction into a Transaction