Skip to content
This repository was archived by the owner on Jan 24, 2025. It is now read-only.

Commit dc5b73c

Browse files
authored
Merge pull request #866 from iotaledger/feat/add-tx-endpoint
Add transaction endpoint
2 parents 6adca9b + b259203 commit dc5b73c

21 files changed

Lines changed: 144 additions & 65 deletions

File tree

components/debugapi/params.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
// ParametersDebugAPI contains the definition of configuration parameters used by the debug API.
88
type ParametersDebugAPI struct {
99
// Enabled whether the DebugAPI component is enabled.
10-
Enabled bool `default:"true" usage:"whether the DebugAPI component is enabled"`
10+
Enabled bool `default:"false" usage:"whether the DebugAPI component is enabled"`
1111

1212
Database struct {
1313
Path string `default:"testnet/debug" usage:"the path to the database folder"`

components/inx/server_commitments.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func (s *Server) ListenToCommitments(req *inx.SlotRangeRequest, srv inx.INX_List
3636
return status.Errorf(codes.NotFound, "commitment slot %d not found", slot)
3737
}
3838

39-
return err
39+
return status.Errorf(codes.Internal, "failed to load commitment for slot %d: %s", slot, err.Error())
4040
}
4141

4242
if err := srv.Send(inxCommitment(commitment)); err != nil {
@@ -178,7 +178,7 @@ func (s *Server) ReadCommitment(_ context.Context, req *inx.CommitmentRequest) (
178178
return nil, status.Errorf(codes.NotFound, "commitment slot %d not found", req.GetCommitmentSlot())
179179
}
180180

181-
return nil, err
181+
return nil, status.Errorf(codes.Internal, "failed to load commitment for slot %d: %s", commitmentSlot, err.Error())
182182
}
183183

184184
if req.GetCommitmentId() != nil {

components/inx/server_node.go

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,41 @@ import (
44
"context"
55
"time"
66

7+
"google.golang.org/grpc/codes"
8+
"google.golang.org/grpc/status"
9+
10+
"github.com/iotaledger/hive.go/ierrors"
11+
"github.com/iotaledger/hive.go/kvstore"
712
"github.com/iotaledger/hive.go/runtime/event"
813
"github.com/iotaledger/hive.go/runtime/workerpool"
914
inx "github.com/iotaledger/inx/go"
1015
"github.com/iotaledger/iota-core/pkg/protocol/engine/syncmanager"
1116
)
1217

13-
func inxNodeStatus(status *syncmanager.SyncStatus) *inx.NodeStatus {
14-
finalizedCommitment, err := deps.Protocol.Engines.Main.Get().Storage.Commitments().Load(status.LatestFinalizedSlot)
18+
func inxNodeStatus(syncStatus *syncmanager.SyncStatus) (*inx.NodeStatus, error) {
19+
finalizedCommitment, err := deps.Protocol.Engines.Main.Get().Storage.Commitments().Load(syncStatus.LatestFinalizedSlot)
1520
if err != nil {
16-
return nil
21+
if ierrors.Is(err, kvstore.ErrKeyNotFound) {
22+
return nil, status.Errorf(codes.NotFound, "finalized commitment (slot %d) not found", syncStatus.LatestFinalizedSlot)
23+
}
24+
25+
return nil, status.Errorf(codes.Internal, "failed to load finalized commitment (slot %d): %s", syncStatus.LatestFinalizedSlot, err.Error())
1726
}
1827

1928
return &inx.NodeStatus{
20-
IsHealthy: status.NodeSynced,
21-
IsBootstrapped: status.NodeBootstrapped,
22-
LastAcceptedBlockSlot: uint32(status.LastAcceptedBlockSlot),
23-
LastConfirmedBlockSlot: uint32(status.LastConfirmedBlockSlot),
24-
LatestCommitment: inxCommitment(status.LatestCommitment),
29+
IsHealthy: syncStatus.NodeSynced,
30+
IsBootstrapped: syncStatus.NodeBootstrapped,
31+
LastAcceptedBlockSlot: uint32(syncStatus.LastAcceptedBlockSlot),
32+
LastConfirmedBlockSlot: uint32(syncStatus.LastConfirmedBlockSlot),
33+
LatestCommitment: inxCommitment(syncStatus.LatestCommitment),
2534
LatestFinalizedCommitment: inxCommitment(finalizedCommitment),
26-
PruningEpoch: uint32(status.LastPrunedEpoch),
27-
HasPruned: status.HasPruned,
28-
}
35+
PruningEpoch: uint32(syncStatus.LastPrunedEpoch),
36+
HasPruned: syncStatus.HasPruned,
37+
}, nil
2938
}
3039

3140
func (s *Server) ReadNodeStatus(context.Context, *inx.NoParams) (*inx.NodeStatus, error) {
32-
return inxNodeStatus(deps.Protocol.Engines.Main.Get().SyncManager.SyncStatus()), nil
41+
return inxNodeStatus(deps.Protocol.Engines.Main.Get().SyncManager.SyncStatus())
3342
}
3443

3544
func (s *Server) ListenToNodeStatus(req *inx.NodeStatusRequest, srv inx.INX_ListenToNodeStatusServer) error {
@@ -56,7 +65,11 @@ func (s *Server) ListenToNodeStatus(req *inx.NodeStatusRequest, srv inx.INX_List
5665
lastUpdateTimer = nil
5766
}
5867

59-
nodeStatus := inxNodeStatus(status)
68+
nodeStatus, err := inxNodeStatus(status)
69+
if err != nil {
70+
Component.LogErrorf("failed to convert sync status to inx node status: %s", err.Error())
71+
return
72+
}
6073

6174
// Use cool-down if the node is syncing
6275
if coolDownDuration > 0 && !nodeStatus.GetIsHealthy() {

components/inx/server_utxo.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"google.golang.org/grpc/status"
88

99
"github.com/iotaledger/hive.go/ierrors"
10+
"github.com/iotaledger/hive.go/kvstore"
1011
"github.com/iotaledger/hive.go/runtime/event"
1112
"github.com/iotaledger/hive.go/runtime/workerpool"
1213
inx "github.com/iotaledger/inx/go"
@@ -204,7 +205,11 @@ func (s *Server) ListenToLedgerUpdates(req *inx.SlotRangeRequest, srv inx.INX_Li
204205
createLedgerUpdatePayloadAndSend := func(slot iotago.SlotIndex, outputs utxoledger.Outputs, spents utxoledger.Spents) error {
205206
commitment, err := deps.Protocol.Engines.Main.Get().Storage.Commitments().Load(slot)
206207
if err != nil {
207-
return status.Errorf(codes.NotFound, "commitment for slot %d not found", slot)
208+
if ierrors.Is(err, kvstore.ErrKeyNotFound) {
209+
return status.Errorf(codes.NotFound, "commitment for slot %d not found", slot)
210+
}
211+
212+
return status.Errorf(codes.Internal, "failed to get commitment for slot %d: %s", slot, err.Error())
208213
}
209214

210215
// Send Begin
@@ -248,7 +253,11 @@ func (s *Server) ListenToLedgerUpdates(req *inx.SlotRangeRequest, srv inx.INX_Li
248253
for currentSlot := startSlot; currentSlot <= endSlot; currentSlot++ {
249254
stateDiff, err := deps.Protocol.Engines.Main.Get().Ledger.SlotDiffs(currentSlot)
250255
if err != nil {
251-
return status.Errorf(codes.NotFound, "ledger update for slot %d not found", currentSlot)
256+
if ierrors.Is(err, kvstore.ErrKeyNotFound) {
257+
return status.Errorf(codes.NotFound, "ledger update for slot %d not found", currentSlot)
258+
}
259+
260+
return status.Errorf(codes.Internal, "failed to get ledger update for slot %d: %s", currentSlot, err.Error())
252261
}
253262

254263
if err := createLedgerUpdatePayloadAndSend(stateDiff.Slot, stateDiff.Outputs, stateDiff.Spents); err != nil {

components/restapi/core/component.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,13 +223,22 @@ func configure() error {
223223
return responseByHeader(c, resp)
224224
}, checkNodeSynced())
225225

226+
routeGroup.GET(api.EndpointWithEchoParameters(api.CoreEndpointTransaction), func(c echo.Context) error {
227+
resp, err := transactionFromTransactionID(c)
228+
if err != nil {
229+
return err
230+
}
231+
232+
return responseByHeader(c, resp)
233+
})
234+
226235
routeGroup.GET(api.EndpointWithEchoParameters(api.CoreEndpointTransactionsIncludedBlock), func(c echo.Context) error {
227-
block, err := blockFromTransactionID(c)
236+
resp, err := blockFromTransactionID(c)
228237
if err != nil {
229238
return err
230239
}
231240

232-
return responseByHeader(c, block)
241+
return responseByHeader(c, resp)
233242
})
234243

235244
routeGroup.GET(api.EndpointWithEchoParameters(api.CoreEndpointTransactionsIncludedBlockMetadata), func(c echo.Context) error {

components/restapi/core/transaction.go

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func blockIDFromTransactionID(c echo.Context) (iotago.BlockID, error) {
2121
func blockFromTransactionID(c echo.Context) (*iotago.Block, error) {
2222
blockID, err := blockIDFromTransactionID(c)
2323
if err != nil {
24-
return nil, ierrors.WithMessagef(echo.ErrBadRequest, "failed to get block ID by transaction ID: %w", err)
24+
return nil, ierrors.Wrap(err, "failed to get block ID by transaction ID")
2525
}
2626

2727
return deps.RequestHandler.BlockFromBlockID(blockID)
@@ -30,16 +30,40 @@ func blockFromTransactionID(c echo.Context) (*iotago.Block, error) {
3030
func blockMetadataFromTransactionID(c echo.Context) (*api.BlockMetadataResponse, error) {
3131
blockID, err := blockIDFromTransactionID(c)
3232
if err != nil {
33-
return nil, ierrors.WithMessagef(echo.ErrBadRequest, "failed to get block ID by transaction ID: %w", err)
33+
return nil, ierrors.Wrap(err, "failed to get block ID by transaction ID")
3434
}
3535

3636
return deps.RequestHandler.BlockMetadataFromBlockID(blockID)
3737
}
3838

39+
func transactionFromTransactionID(c echo.Context) (*iotago.Transaction, error) {
40+
txID, err := httpserver.ParseTransactionIDParam(c, api.ParameterTransactionID)
41+
if err != nil {
42+
return nil, ierrors.Wrap(err, "failed to parse transaction ID")
43+
}
44+
45+
blockID, err := deps.RequestHandler.BlockIDFromTransactionID(txID)
46+
if err != nil {
47+
return nil, ierrors.Wrap(err, "failed to get block ID by transaction ID")
48+
}
49+
50+
block, err := deps.RequestHandler.ModelBlockFromBlockID(blockID)
51+
if err != nil {
52+
return nil, ierrors.Wrap(err, "failed to get block by block ID")
53+
}
54+
55+
tx, isTransaction := block.SignedTransaction()
56+
if !isTransaction {
57+
return nil, ierrors.WithMessagef(echo.ErrInternalServerError, "block %s does not contain a transaction", blockID)
58+
}
59+
60+
return tx.Transaction, nil
61+
}
62+
3963
func transactionMetadataFromTransactionID(c echo.Context) (*api.TransactionMetadataResponse, error) {
4064
txID, err := httpserver.ParseTransactionIDParam(c, api.ParameterTransactionID)
4165
if err != nil {
42-
return nil, ierrors.Wrapf(err, "failed to parse transaction ID %s", c.Param(api.ParameterTransactionID))
66+
return nil, ierrors.Wrap(err, "failed to parse transaction ID")
4367
}
4468

4569
return deps.RequestHandler.TransactionMetadataFromTransactionID(txID)

config_defaults.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
}
7575
},
7676
"debugAPI": {
77-
"enabled": true,
77+
"enabled": false,
7878
"db": {
7979
"path": "testnet/debug",
8080
"maxOpenDBs": 2,

documentation/configuration.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ Example:
235235

236236
| Name | Description | Type | Default value |
237237
| ------------------ | ----------------------------------------- | ------- | ------------- |
238-
| enabled | Whether the DebugAPI component is enabled | boolean | true |
238+
| enabled | Whether the DebugAPI component is enabled | boolean | false |
239239
| [db](#debugapi_db) | Configuration for db | object | |
240240

241241
### <a id="debugapi_db"></a> Db
@@ -258,7 +258,7 @@ Example:
258258
```json
259259
{
260260
"debugAPI": {
261-
"enabled": true,
261+
"enabled": false,
262262
"db": {
263263
"path": "testnet/debug",
264264
"maxOpenDBs": 2,

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ require (
2929
github.com/iotaledger/hive.go/stringify v0.0.0-20240320122938-13a946cf3c7a
3030
github.com/iotaledger/inx-app v1.0.0-rc.3.0.20240307101848-db58eb9353ec
3131
github.com/iotaledger/inx/go v1.0.0-rc.2.0.20240307100839-48553e1d2022
32-
github.com/iotaledger/iota.go/v4 v4.0.0-20240322111205-845f859ca28c
32+
github.com/iotaledger/iota.go/v4 v4.0.0-20240322114706-82a1f8a8b70c
3333
github.com/labstack/echo/v4 v4.11.4
3434
github.com/labstack/gommon v0.4.2
3535
github.com/libp2p/go-libp2p v0.33.1

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,8 @@ github.com/iotaledger/inx/go v1.0.0-rc.2.0.20240307100839-48553e1d2022 h1:I178Sa
325325
github.com/iotaledger/inx/go v1.0.0-rc.2.0.20240307100839-48553e1d2022/go.mod h1:jTFxIWiMUdAwO263jlJCSWcNLqEkgYEVOFXfjp5aNJM=
326326
github.com/iotaledger/iota-crypto-demo v0.0.0-20240320124000-d02f37a4fdff h1:Do8fakxvFaj7dLckoo/z+mRyBdZo8QvT8HcgnQlG2Sg=
327327
github.com/iotaledger/iota-crypto-demo v0.0.0-20240320124000-d02f37a4fdff/go.mod h1:aVEutEWFnhDNJBxtVuzy2BeTN+8FAlnR83k7hKV0CFE=
328-
github.com/iotaledger/iota.go/v4 v4.0.0-20240322111205-845f859ca28c h1:xnaAczQXgcm4FL/z6q/r5WqUsyxqsUcs/hEdikQjjQ0=
329-
github.com/iotaledger/iota.go/v4 v4.0.0-20240322111205-845f859ca28c/go.mod h1:qn/63CB0/jE1em6ewqDSiz+ovS+E/os7K5b7g2pmJFg=
328+
github.com/iotaledger/iota.go/v4 v4.0.0-20240322114706-82a1f8a8b70c h1:0uqpCv2txjbVi1E5AFvXkUGmTMiEX1nPzmTFH1Bfk6c=
329+
github.com/iotaledger/iota.go/v4 v4.0.0-20240322114706-82a1f8a8b70c/go.mod h1:qn/63CB0/jE1em6ewqDSiz+ovS+E/os7K5b7g2pmJFg=
330330
github.com/ipfs/boxo v0.18.0 h1:MOL9/AgoV3e7jlVMInicaSdbgralfqSsbkc31dZ9tmw=
331331
github.com/ipfs/boxo v0.18.0/go.mod h1:pIZgTWdm3k3pLF9Uq6MB8JEcW07UDwNJjlXW1HELW80=
332332
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=

0 commit comments

Comments
 (0)