From c00ddae28dfb21ed8db69e1aec9cca893c1132c4 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Fri, 12 Apr 2024 14:28:49 -0400 Subject: [PATCH 01/57] Add cursor for getTransactions --- cmd/soroban-rpc/internal/config/config.go | 2 + cmd/soroban-rpc/internal/daemon/daemon.go | 1 + .../internal/daemon/interfaces/interfaces.go | 7 ++ cmd/soroban-rpc/internal/db/transaction.go | 21 ++++ cmd/soroban-rpc/internal/events/cursor.go | 20 ++-- cmd/soroban-rpc/internal/events/events.go | 13 ++- cmd/soroban-rpc/internal/jsonrpc.go | 8 ++ .../internal/methods/get_events.go | 8 +- .../internal/methods/get_transactions.go | 105 ++++++++++++++++++ .../internal/transactions/cursor.go | 47 ++++++++ 10 files changed, 214 insertions(+), 18 deletions(-) create mode 100644 cmd/soroban-rpc/internal/db/transaction.go create mode 100644 cmd/soroban-rpc/internal/methods/get_transactions.go create mode 100644 cmd/soroban-rpc/internal/transactions/cursor.go diff --git a/cmd/soroban-rpc/internal/config/config.go b/cmd/soroban-rpc/internal/config/config.go index 15e69f6b..b93812a8 100644 --- a/cmd/soroban-rpc/internal/config/config.go +++ b/cmd/soroban-rpc/internal/config/config.go @@ -25,6 +25,7 @@ type Config struct { CheckpointFrequency uint32 CoreRequestTimeout time.Duration DefaultEventsLimit uint + DefaultTransactionsLimit uint EventLedgerRetentionWindow uint32 FriendbotURL string HistoryArchiveURLs []string @@ -33,6 +34,7 @@ type Config struct { LogFormat LogFormat LogLevel logrus.Level MaxEventsLimit uint + MaxTransactionsLimit uint MaxHealthyLedgerLatency time.Duration NetworkPassphrase string PreflightWorkerCount uint diff --git a/cmd/soroban-rpc/internal/daemon/daemon.go b/cmd/soroban-rpc/internal/daemon/daemon.go index 9e21f97a..aa3b0e7d 100644 --- a/cmd/soroban-rpc/internal/daemon/daemon.go +++ b/cmd/soroban-rpc/internal/daemon/daemon.go @@ -248,6 +248,7 @@ func MustNew(cfg *config.Config) *Daemon { TransactionStore: transactionStore, Logger: logger, LedgerReader: db.NewLedgerReader(dbConn), + TransactionReader: db.NewTransactionReader(dbConn), LedgerEntryReader: db.NewLedgerEntryReader(dbConn), PreflightGetter: preflightWorkerPool, }) diff --git a/cmd/soroban-rpc/internal/daemon/interfaces/interfaces.go b/cmd/soroban-rpc/internal/daemon/interfaces/interfaces.go index 529ecdef..c3b42148 100644 --- a/cmd/soroban-rpc/internal/daemon/interfaces/interfaces.go +++ b/cmd/soroban-rpc/internal/daemon/interfaces/interfaces.go @@ -20,3 +20,10 @@ type CoreClient interface { Info(ctx context.Context) (*proto.InfoResponse, error) SubmitTransaction(context.Context, string) (*proto.TXResponse, error) } + +type Cursor interface { + String() string + MarshalJSON() ([]byte, error) + UnmarshalJSON(b []byte) error + Cmp(other Cursor) int +} diff --git a/cmd/soroban-rpc/internal/db/transaction.go b/cmd/soroban-rpc/internal/db/transaction.go new file mode 100644 index 00000000..e0871fef --- /dev/null +++ b/cmd/soroban-rpc/internal/db/transaction.go @@ -0,0 +1,21 @@ +package db + +type TransactionReader interface{} + +type transactionReader struct { + db *DB +} + +func NewTransactionReader(db *DB) TransactionReader { + return transactionReader{db: db} +} + +type TransactionWriter interface{} + +type transactionWriter struct { + db *DB +} + +func NewTransactionWriter(db *DB) TransactionWriter { + return transactionWriter{db: db} +} diff --git a/cmd/soroban-rpc/internal/events/cursor.go b/cmd/soroban-rpc/internal/events/cursor.go index 3fbfbecb..886d103d 100644 --- a/cmd/soroban-rpc/internal/events/cursor.go +++ b/cmd/soroban-rpc/internal/events/cursor.go @@ -8,6 +8,8 @@ import ( "strings" "github.com/stellar/go/toid" + + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/daemon/interfaces" ) // Cursor represents the position of a Soroban event. @@ -98,17 +100,19 @@ func cmp(a, b uint32) int { // 0 is returned if the c is equal to other. // 1 is returned if c is greater than other. // -1 is returned if c is less than other. -func (c Cursor) Cmp(other Cursor) int { - if c.Ledger == other.Ledger { - if c.Tx == other.Tx { - if c.Op == other.Op { - return cmp(c.Event, other.Event) +func (c Cursor) Cmp(other interfaces.Cursor) int { + otherCursor := other.(*Cursor) + + if c.Ledger == otherCursor.Ledger { + if c.Tx == otherCursor.Tx { + if c.Op == otherCursor.Op { + return cmp(c.Event, otherCursor.Event) } - return cmp(c.Op, other.Op) + return cmp(c.Op, otherCursor.Op) } - return cmp(c.Tx, other.Tx) + return cmp(c.Tx, otherCursor.Tx) } - return cmp(c.Ledger, other.Ledger) + return cmp(c.Ledger, otherCursor.Ledger) } var ( diff --git a/cmd/soroban-rpc/internal/events/events.go b/cmd/soroban-rpc/internal/events/events.go index 39fdc4ce..f2abf063 100644 --- a/cmd/soroban-rpc/internal/events/events.go +++ b/cmd/soroban-rpc/internal/events/events.go @@ -128,7 +128,7 @@ func (m *MemoryStore) Scan(eventRange Range, f ScanFunction) (lastLedgerInWindow timestamp := bucket.LedgerCloseTimestamp for _, event := range events { cur := event.cursor(bucket.LedgerSeq) - if eventRange.End.Cmp(cur) <= 0 { + if eventRange.End.Cmp(&cur) <= 0 { return } var diagnosticEvent xdr.DiagnosticEvent @@ -153,7 +153,7 @@ func (m *MemoryStore) validateRange(eventRange *Range) error { } firstBucket := m.eventsByLedger.Get(0) min := Cursor{Ledger: firstBucket.LedgerSeq} - if eventRange.Start.Cmp(min) < 0 { + if eventRange.Start.Cmp(&min) < 0 { if eventRange.ClampStart { eventRange.Start = min } else { @@ -161,10 +161,10 @@ func (m *MemoryStore) validateRange(eventRange *Range) error { } } max := Cursor{Ledger: min.Ledger + m.eventsByLedger.Len()} - if eventRange.Start.Cmp(max) >= 0 { + if eventRange.Start.Cmp(&max) >= 0 { return errors.New("start is after newest ledger") } - if eventRange.End.Cmp(max) > 0 { + if eventRange.End.Cmp(&max) > 0 { if eventRange.ClampEnd { eventRange.End = max } else { @@ -172,7 +172,7 @@ func (m *MemoryStore) validateRange(eventRange *Range) error { } } - if eventRange.Start.Cmp(eventRange.End) >= 0 { + if eventRange.Start.Cmp(&eventRange.End) >= 0 { return errors.New("start is not before end") } @@ -184,7 +184,8 @@ func (m *MemoryStore) validateRange(eventRange *Range) error { // events must be sorted in ascending order. func seek(events []event, cursor Cursor) []event { j := sort.Search(len(events), func(i int) bool { - return cursor.Cmp(events[i].cursor(cursor.Ledger)) <= 0 + cur := events[i].cursor(cursor.Ledger) + return cursor.Cmp(&cur) <= 0 }) return events[j:] } diff --git a/cmd/soroban-rpc/internal/jsonrpc.go b/cmd/soroban-rpc/internal/jsonrpc.go index d122b9a0..106a93fb 100644 --- a/cmd/soroban-rpc/internal/jsonrpc.go +++ b/cmd/soroban-rpc/internal/jsonrpc.go @@ -50,6 +50,7 @@ type HandlerParams struct { TransactionStore *transactions.MemoryStore LedgerEntryReader db.LedgerEntryReader LedgerReader db.LedgerReader + TransactionReader db.TransactionReader Logger *log.Entry PreflightGetter methods.PreflightGetter Daemon interfaces.Daemon @@ -190,6 +191,13 @@ func NewJSONRPCHandler(cfg *config.Config, params HandlerParams) Handler { queueLimit: cfg.RequestBacklogGetTransactionQueueLimit, requestDurationLimit: cfg.MaxGetTransactionExecutionDuration, }, + { + methodName: "getTransactions", + underlyingHandler: methods.NewGetTransactionsHandler(params.Logger, params.LedgerReader, params.TransactionReader, cfg.MaxTransactionsLimit, cfg.DefaultTransactionsLimit), + longName: "get_transactions", + queueLimit: cfg.RequestBacklogSendTransactionQueueLimit, + requestDurationLimit: cfg.MaxSendTransactionExecutionDuration, + }, { methodName: "sendTransaction", underlyingHandler: methods.NewSendTransactionHandler(params.Daemon, params.Logger, params.TransactionStore, cfg.NetworkPassphrase), diff --git a/cmd/soroban-rpc/internal/methods/get_events.go b/cmd/soroban-rpc/internal/methods/get_events.go index dda0fa06..73105760 100644 --- a/cmd/soroban-rpc/internal/methods/get_events.go +++ b/cmd/soroban-rpc/internal/methods/get_events.go @@ -80,9 +80,9 @@ type EventInfo struct { } type GetEventsRequest struct { - StartLedger uint32 `json:"startLedger,omitempty"` - Filters []EventFilter `json:"filters"` - Pagination *PaginationOptions `json:"pagination,omitempty"` + StartLedger uint32 `json:"startLedger,omitempty"` + Filters []EventFilter `json:"filters"` + Pagination *EventsPaginationOptions `json:"pagination,omitempty"` } func (g *GetEventsRequest) Valid(maxLimit uint) error { @@ -289,7 +289,7 @@ func (s *SegmentFilter) UnmarshalJSON(p []byte) error { return nil } -type PaginationOptions struct { +type EventsPaginationOptions struct { Cursor *events.Cursor `json:"cursor,omitempty"` Limit uint `json:"limit,omitempty"` } diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go new file mode 100644 index 00000000..bfcc0313 --- /dev/null +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -0,0 +1,105 @@ +package methods + +import ( + "context" + + "github.com/creachadair/jrpc2" + "github.com/creachadair/jrpc2/handler" + "github.com/stellar/go/support/errors" + "github.com/stellar/go/support/log" + + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/db" + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/transactions" +) + +type TransactionsPaginationOptions struct { + Cursor *transactions.Cursor `json:"cursor,omitempty"` + Limit uint `json:"limit,omitempty"` +} + +type GetTransactionsRequest struct { + StartLedger uint32 + EndLedger uint32 + Pagination *TransactionsPaginationOptions +} + +func (req GetTransactionsRequest) valid() error { + // Validate the start and end ledger sequence + if req.StartLedger < 0 { + return errors.New("start ledger cannot be negative") + } + if req.EndLedger < req.StartLedger { + return errors.New("end ledger cannot be less than start ledger") + } + + return nil +} + +type GetTransactionsResponse struct { + Transactions []transactions.Transaction `json:"transactions"` + LatestLedger int64 `json:"latestLedger"` + LatestLedgerCloseTimestamp int64 `json:"latestLedgerCloseTimestamp"` +} + +type transactionsRPCHandler struct { + ledgerReader db.LedgerReader + transactionReader db.TransactionReader + maxLimit uint + defaultLimit uint + logger *log.Entry +} + +//func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Context, request GetTransactionsRequest) (GetTransactionsResponse, error) { +// err := request.valid() +// if err != nil { +// return GetTransactionsResponse{}, &jrpc2.Error{ +// Code: jrpc2.InvalidParams, +// Message: err.Error(), +// } +// } + +//start := transactions.Cursor{LedgerSequence: request.StartLedger} +//end := transactions.Cursor{LedgerSequence: request.EndLedger} +//limit := h.defaultLimit +//if request.Pagination != nil { +// if request.Pagination.Cursor != nil { +// start = *request.Pagination.Cursor +// // increment event index because, when paginating, +// // we start with the item right after the cursor +// start.TxIdx++ +// } +// if request.Pagination.Limit > 0 { +// limit = request.Pagination.Limit +// } +//} +//transactions := make([]transactions.Transaction, h.defaultLimit) +//for ledgerSeq := request.StartLedger; ledgerSeq <= request.EndLedger; ledgerSeq++ { +// ledger, found, err := h.ledgerReader.GetLedger(ctx, ledgerSeq) +// if (err != nil) || (!found) { +// return GetTransactionsResponse{}, &jrpc2.Error{ +// Code: jrpc2.InternalError, +// Message: "could not get ledger sequence", +// } +// } +// +// txCount := ledger.CountTransactions() +// for i := 0; i < txCount; i++ { +// +// } +// +//} +//} + +func NewGetTransactionsHandler(logger *log.Entry, ledgerReader db.LedgerReader, transactionReader db.TransactionReader, maxLimit, defaultLimit uint) jrpc2.Handler { + transactionsHandler := transactionsRPCHandler{ + ledgerReader: ledgerReader, + transactionReader: transactionReader, + maxLimit: maxLimit, + defaultLimit: defaultLimit, + logger: logger, + } + + return handler.New(func(context context.Context, request GetTransactionsRequest) (GetTransactionsResponse, error) { + return transactionsHandler.getTransactionsByLedgerSequence(context, request) + }) +} diff --git a/cmd/soroban-rpc/internal/transactions/cursor.go b/cmd/soroban-rpc/internal/transactions/cursor.go new file mode 100644 index 00000000..14021d1d --- /dev/null +++ b/cmd/soroban-rpc/internal/transactions/cursor.go @@ -0,0 +1,47 @@ +package transactions + +import ( + "encoding/json" + "fmt" + + "github.com/stellar/go/toid" + + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/daemon/interfaces" +) + +type Cursor struct { + // LedgerSequence is the sequence of the ledger which emitted the event. + LedgerSequence uint32 + // TxIdx is the index of the transaction within the ledger which emitted the event. + TxIdx uint32 + // Op is the index of the operation within the transaction which emitted the event. + // Note: Currently, there is no use for it (events are transaction-wide and not operation-specific) + // but we keep it in order to make the API future-proof. + OpIdx uint32 +} + +// String returns a string representation of this cursor +func (c Cursor) String() string { + return fmt.Sprintf( + "%019d", + toid.New(int32(c.LedgerSequence), int32(c.TxIdx), int32(c.OpIdx)).ToInt64(), + ) +} + +// MarshalJSON marshals the cursor into JSON +func (c Cursor) MarshalJSON() ([]byte, error) { + return json.Marshal(c.String()) +} + +// UnmarshalJSON unmarshalls a cursor from the given JSON +func (c Cursor) UnmarshalJSON(b []byte) error { + return nil +} + +// Cmp compares two cursors. +// 0 is returned if the c is equal to other. +// 1 is returned if c is greater than other. +// -1 is returned if c is less than other. +func (c Cursor) Cmp(other interfaces.Cursor) int { + return 0 +} From 2467dbe1e082613efc5496e3eb4e8486c22d9f13 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Fri, 12 Apr 2024 15:33:57 -0400 Subject: [PATCH 02/57] Add validation of pagination and range --- cmd/soroban-rpc/internal/jsonrpc.go | 3 +- .../internal/methods/get_transactions.go | 132 ++++++++++++------ 2 files changed, 88 insertions(+), 47 deletions(-) diff --git a/cmd/soroban-rpc/internal/jsonrpc.go b/cmd/soroban-rpc/internal/jsonrpc.go index 106a93fb..9b151d4f 100644 --- a/cmd/soroban-rpc/internal/jsonrpc.go +++ b/cmd/soroban-rpc/internal/jsonrpc.go @@ -50,7 +50,6 @@ type HandlerParams struct { TransactionStore *transactions.MemoryStore LedgerEntryReader db.LedgerEntryReader LedgerReader db.LedgerReader - TransactionReader db.TransactionReader Logger *log.Entry PreflightGetter methods.PreflightGetter Daemon interfaces.Daemon @@ -193,7 +192,7 @@ func NewJSONRPCHandler(cfg *config.Config, params HandlerParams) Handler { }, { methodName: "getTransactions", - underlyingHandler: methods.NewGetTransactionsHandler(params.Logger, params.LedgerReader, params.TransactionReader, cfg.MaxTransactionsLimit, cfg.DefaultTransactionsLimit), + underlyingHandler: methods.NewGetTransactionsHandler(params.Logger, params.LedgerReader, params.LedgerEntryReader, cfg.MaxTransactionsLimit, cfg.DefaultTransactionsLimit), longName: "get_transactions", queueLimit: cfg.RequestBacklogSendTransactionQueueLimit, requestDurationLimit: cfg.MaxSendTransactionExecutionDuration, diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index bfcc0313..1146591b 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -17,13 +17,37 @@ type TransactionsPaginationOptions struct { Limit uint `json:"limit,omitempty"` } +// Range defines a [Start, End] interval of ledgers. +type Range struct { + // Start defines the (inclusive) start of the range. + Start transactions.Cursor + // End defines the (inclusive) end of the range. + End transactions.Cursor +} + +func (r Range) isValid(ctx context.Context, ledgerReader db.LedgerReader, ledgerEntryReader db.LedgerEntryReader) error { + //tx, err := ledgerEntryReader.NewTx(ctx) + //if err != nil { + // return errors.New("could not read transaction") + //} + //defer func() { + // _ = tx.Done() + //}() + // + //latestLedger, err := tx.GetLatestLedgerSequence() + //if err != nil { + // return errors.New("could not get latest ledger") + //} + return nil +} + type GetTransactionsRequest struct { StartLedger uint32 EndLedger uint32 Pagination *TransactionsPaginationOptions } -func (req GetTransactionsRequest) valid() error { +func (req GetTransactionsRequest) isValid() error { // Validate the start and end ledger sequence if req.StartLedger < 0 { return errors.New("start ledger cannot be negative") @@ -43,57 +67,75 @@ type GetTransactionsResponse struct { type transactionsRPCHandler struct { ledgerReader db.LedgerReader - transactionReader db.TransactionReader + ledgerEntryReader db.LedgerEntryReader maxLimit uint defaultLimit uint logger *log.Entry } -//func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Context, request GetTransactionsRequest) (GetTransactionsResponse, error) { -// err := request.valid() -// if err != nil { -// return GetTransactionsResponse{}, &jrpc2.Error{ -// Code: jrpc2.InvalidParams, -// Message: err.Error(), -// } -// } - -//start := transactions.Cursor{LedgerSequence: request.StartLedger} -//end := transactions.Cursor{LedgerSequence: request.EndLedger} -//limit := h.defaultLimit -//if request.Pagination != nil { -// if request.Pagination.Cursor != nil { -// start = *request.Pagination.Cursor -// // increment event index because, when paginating, -// // we start with the item right after the cursor -// start.TxIdx++ -// } -// if request.Pagination.Limit > 0 { -// limit = request.Pagination.Limit -// } -//} -//transactions := make([]transactions.Transaction, h.defaultLimit) -//for ledgerSeq := request.StartLedger; ledgerSeq <= request.EndLedger; ledgerSeq++ { -// ledger, found, err := h.ledgerReader.GetLedger(ctx, ledgerSeq) -// if (err != nil) || (!found) { -// return GetTransactionsResponse{}, &jrpc2.Error{ -// Code: jrpc2.InternalError, -// Message: "could not get ledger sequence", -// } -// } -// -// txCount := ledger.CountTransactions() -// for i := 0; i < txCount; i++ { -// -// } -// -//} -//} - -func NewGetTransactionsHandler(logger *log.Entry, ledgerReader db.LedgerReader, transactionReader db.TransactionReader, maxLimit, defaultLimit uint) jrpc2.Handler { +func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Context, request GetTransactionsRequest) (GetTransactionsResponse, error) { + err := request.isValid() + if err != nil { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } + } + + start := transactions.Cursor{LedgerSequence: request.StartLedger} + end := transactions.Cursor{LedgerSequence: request.EndLedger} + limit := h.defaultLimit + if request.Pagination != nil { + if request.Pagination.Cursor != nil { + start = *request.Pagination.Cursor + // increment event index because, when paginating, + // we start with the item right after the cursor + start.TxIdx++ + } + if request.Pagination.Limit > 0 { + limit = request.Pagination.Limit + } + } + + // Validate the range + ledgerRange := Range{ + Start: start, + End: end, + } + err = ledgerRange.isValid(ctx, h.ledgerReader, h.ledgerEntryReader) + if err != nil { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } + } + + //transactions := make([]transactions.Transaction, limit) + //for i := ledgerRange.Start.LedgerSequence; i <= ledgerRange.End.LedgerSequence; i++ { + // + //} + + //for ledgerSeq := request.StartLedger; ledgerSeq <= request.EndLedger; ledgerSeq++ { + // ledger, found, err := h.ledgerReader.GetLedger(ctx, ledgerSeq) + // if (err != nil) || (!found) { + // return GetTransactionsResponse{}, &jrpc2.Error{ + // Code: jrpc2.InternalError, + // Message: "could not get ledger sequence", + // } + // } + // + // txCount := ledger.CountTransactions() + // for i := 0; i < txCount; i++ { + // + // } + // + //} +} + +func NewGetTransactionsHandler(logger *log.Entry, ledgerReader db.LedgerReader, ledgerEntryReader db.LedgerEntryReader, maxLimit, defaultLimit uint) jrpc2.Handler { transactionsHandler := transactionsRPCHandler{ ledgerReader: ledgerReader, - transactionReader: transactionReader, + ledgerEntryReader: ledgerEntryReader, maxLimit: maxLimit, defaultLimit: defaultLimit, logger: logger, From 6aa348d4bfbd7e39de37901120fb65ce060fd973 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Mon, 15 Apr 2024 14:06:00 -0400 Subject: [PATCH 03/57] implement getTransactions handler - 1 --- cmd/soroban-rpc/internal/daemon/daemon.go | 1 - cmd/soroban-rpc/internal/db/ledger.go | 5 + cmd/soroban-rpc/internal/jsonrpc.go | 2 +- .../internal/methods/get_events_test.go | 10 +- .../methods/get_latest_ledger_test.go | 4 + .../internal/methods/get_transactions.go | 170 +++++++++++++++--- .../internal/transactions/cursor.go | 8 + 7 files changed, 168 insertions(+), 32 deletions(-) diff --git a/cmd/soroban-rpc/internal/daemon/daemon.go b/cmd/soroban-rpc/internal/daemon/daemon.go index aa3b0e7d..9e21f97a 100644 --- a/cmd/soroban-rpc/internal/daemon/daemon.go +++ b/cmd/soroban-rpc/internal/daemon/daemon.go @@ -248,7 +248,6 @@ func MustNew(cfg *config.Config) *Daemon { TransactionStore: transactionStore, Logger: logger, LedgerReader: db.NewLedgerReader(dbConn), - TransactionReader: db.NewTransactionReader(dbConn), LedgerEntryReader: db.NewLedgerEntryReader(dbConn), PreflightGetter: preflightWorkerPool, }) diff --git a/cmd/soroban-rpc/internal/db/ledger.go b/cmd/soroban-rpc/internal/db/ledger.go index 1b4b0aa2..a8676aa2 100644 --- a/cmd/soroban-rpc/internal/db/ledger.go +++ b/cmd/soroban-rpc/internal/db/ledger.go @@ -17,6 +17,7 @@ type StreamLedgerFn func(xdr.LedgerCloseMeta) error type LedgerReader interface { GetLedger(ctx context.Context, sequence uint32) (xdr.LedgerCloseMeta, bool, error) + GetLedgers(ctx context.Context, startSequence uint32, endSequence uint32) ([]xdr.LedgerCloseMeta, error) StreamAllLedgers(ctx context.Context, f StreamLedgerFn) error } @@ -69,6 +70,10 @@ func (r ledgerReader) GetLedger(ctx context.Context, sequence uint32) (xdr.Ledge } } +func (r ledgerReader) GetLedgers(ctx context.Context, startSequence uint32, endSequence uint32) ([]xdr.LedgerCloseMeta, error) { + return []xdr.LedgerCloseMeta{}, nil +} + type ledgerWriter struct { stmtCache *sq.StmtCache } diff --git a/cmd/soroban-rpc/internal/jsonrpc.go b/cmd/soroban-rpc/internal/jsonrpc.go index 9b151d4f..709a31a1 100644 --- a/cmd/soroban-rpc/internal/jsonrpc.go +++ b/cmd/soroban-rpc/internal/jsonrpc.go @@ -192,7 +192,7 @@ func NewJSONRPCHandler(cfg *config.Config, params HandlerParams) Handler { }, { methodName: "getTransactions", - underlyingHandler: methods.NewGetTransactionsHandler(params.Logger, params.LedgerReader, params.LedgerEntryReader, cfg.MaxTransactionsLimit, cfg.DefaultTransactionsLimit), + underlyingHandler: methods.NewGetTransactionsHandler(params.Logger, params.LedgerReader, params.LedgerEntryReader, cfg.MaxTransactionsLimit, cfg.DefaultTransactionsLimit, cfg.NetworkPassphrase), longName: "get_transactions", queueLimit: cfg.RequestBacklogSendTransactionQueueLimit, requestDurationLimit: cfg.MaxSendTransactionExecutionDuration, diff --git a/cmd/soroban-rpc/internal/methods/get_events_test.go b/cmd/soroban-rpc/internal/methods/get_events_test.go index 087a3ffd..7d86aedc 100644 --- a/cmd/soroban-rpc/internal/methods/get_events_test.go +++ b/cmd/soroban-rpc/internal/methods/get_events_test.go @@ -410,7 +410,7 @@ func TestGetEventsRequestValid(t *testing.T) { assert.EqualError(t, (&GetEventsRequest{ StartLedger: 1, Filters: []EventFilter{}, - Pagination: &PaginationOptions{Cursor: &events.Cursor{}}, + Pagination: &EventsPaginationOptions{Cursor: &events.Cursor{}}, }).Valid(1000), "startLedger and cursor cannot both be set") assert.NoError(t, (&GetEventsRequest{ @@ -422,7 +422,7 @@ func TestGetEventsRequestValid(t *testing.T) { assert.EqualError(t, (&GetEventsRequest{ StartLedger: 1, Filters: []EventFilter{}, - Pagination: &PaginationOptions{Limit: 1001}, + Pagination: &EventsPaginationOptions{Limit: 1001}, }).Valid(1000), "limit must not exceed 1000") assert.EqualError(t, (&GetEventsRequest{ @@ -932,7 +932,7 @@ func TestGetEvents(t *testing.T) { results, err := handler.getEvents(GetEventsRequest{ StartLedger: 1, Filters: []EventFilter{}, - Pagination: &PaginationOptions{Limit: 10}, + Pagination: &EventsPaginationOptions{Limit: 10}, }) assert.NoError(t, err) @@ -1016,7 +1016,7 @@ func TestGetEvents(t *testing.T) { defaultLimit: 100, } results, err := handler.getEvents(GetEventsRequest{ - Pagination: &PaginationOptions{ + Pagination: &EventsPaginationOptions{ Cursor: id, Limit: 2, }, @@ -1048,7 +1048,7 @@ func TestGetEvents(t *testing.T) { assert.Equal(t, GetEventsResponse{expected, 5}, results) results, err = handler.getEvents(GetEventsRequest{ - Pagination: &PaginationOptions{ + Pagination: &EventsPaginationOptions{ Cursor: &events.Cursor{Ledger: 5, Tx: 2, Op: 0, Event: 1}, Limit: 2, }, diff --git a/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go b/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go index 30e05afa..8b1c3fe5 100644 --- a/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go +++ b/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go @@ -58,6 +58,10 @@ func (ledgerReader *ConstantLedgerReader) StreamAllLedgers(ctx context.Context, return nil } +func (ledgerReader *ConstantLedgerReader) GetLedgers(ctx context.Context, startSequence uint32, endSequence uint32) ([]xdr.LedgerCloseMeta, error) { + return []xdr.LedgerCloseMeta{}, nil +} + func createLedger(ledgerSequence uint32, protocolVersion uint32, hash byte) xdr.LedgerCloseMeta { return xdr.LedgerCloseMeta{ V: 1, diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 1146591b..bb780528 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -2,11 +2,14 @@ package methods import ( "context" + "encoding/hex" "github.com/creachadair/jrpc2" "github.com/creachadair/jrpc2/handler" + "github.com/stellar/go/network" "github.com/stellar/go/support/errors" "github.com/stellar/go/support/log" + "github.com/stellar/go/xdr" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/db" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/transactions" @@ -59,10 +62,21 @@ func (req GetTransactionsRequest) isValid() error { return nil } +type TransactionInfo struct { + Result []byte // XDR encoded xdr.TransactionResult + Meta []byte // XDR encoded xdr.TransactionMeta + Envelope []byte // XDR encoded xdr.TransactionEnvelope + FeeBump bool + ApplicationOrder int32 + Successful bool + LedgerSequence uint +} + type GetTransactionsResponse struct { - Transactions []transactions.Transaction `json:"transactions"` - LatestLedger int64 `json:"latestLedger"` - LatestLedgerCloseTimestamp int64 `json:"latestLedgerCloseTimestamp"` + Transactions []TransactionInfo `json:"transactions"` + LatestLedger int64 `json:"latestLedger"` + LatestLedgerCloseTimestamp int64 `json:"latestLedgerCloseTimestamp"` + Pagination *TransactionsPaginationOptions } type transactionsRPCHandler struct { @@ -71,6 +85,7 @@ type transactionsRPCHandler struct { maxLimit uint defaultLimit uint logger *log.Entry + networkPassphrase string } func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Context, request GetTransactionsRequest) (GetTransactionsResponse, error) { @@ -82,8 +97,17 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont } } - start := transactions.Cursor{LedgerSequence: request.StartLedger} - end := transactions.Cursor{LedgerSequence: request.EndLedger} + start := transactions.NewCursor(request.StartLedger, 0, 0) + endLedger, found, err := h.ledgerReader.GetLedger(ctx, request.EndLedger) + if err != nil || !found { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } + } + end := transactions.NewCursor(request.EndLedger, uint32(endLedger.CountTransactions()), 0) + + // Move start to pagination cursor limit := h.defaultLimit if request.Pagination != nil { if request.Pagination.Cursor != nil { @@ -110,35 +134,131 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont } } - //transactions := make([]transactions.Transaction, limit) - //for i := ledgerRange.Start.LedgerSequence; i <= ledgerRange.End.LedgerSequence; i++ { - // - //} + // Get all ledgers within the range from db + ledgers, err := h.ledgerReader.GetLedgers(ctx, ledgerRange.Start.LedgerSequence, ledgerRange.End.LedgerSequence) + if err != nil { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } + } + + // Iterate through each ledger and its transactions until limit or end range is reached + txns := make([]TransactionInfo, limit) + var cursor transactions.Cursor + for _, lcm := range ledgers { + // Build transaction envelopes in the ledger + byHash := map[xdr.Hash]xdr.TransactionEnvelope{} + for _, tx := range lcm.TransactionEnvelopes() { + hash, err := network.HashTransactionInEnvelope(tx, h.networkPassphrase) + if err != nil { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } + } + byHash[hash] = tx + } + + txCount := lcm.CountTransactions() + for i := ledgerRange.Start.TxIdx; i < uint32(txCount); i++ { + cursor = transactions.NewCursor(lcm.LedgerSequence(), i, 0) + if ledgerRange.End.Cmp(cursor) <= 0 { + break + } + + hash := lcm.TransactionHash(int(i)) + envelope, ok := byHash[hash] + if !ok { + hexHash := hex.EncodeToString(hash[:]) + err = errors.Errorf("unknown tx hash in LedgerCloseMeta: %v", hexHash) + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } + } + txResult := lcm.TransactionResultPair(int(i)) + unsafeMeta := lcm.TxApplyProcessing(int(i)) + + txInfo := TransactionInfo{ + FeeBump: envelope.IsFeeBump(), + ApplicationOrder: int32(i + 1), + Successful: txResult.Result.Successful(), + LedgerSequence: uint(lcm.LedgerSequence()), + } + if txInfo.Result, err = txResult.Result.MarshalBinary(); err != nil { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } + } + if txInfo.Meta, err = unsafeMeta.MarshalBinary(); err != nil { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } + } + if txInfo.Envelope, err = envelope.MarshalBinary(); err != nil { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } + } + + txns = append(txns, txInfo) + if len(txns) >= int(limit) { + break + } + } + } + + tx, err := h.ledgerEntryReader.NewTx(ctx) + if err != nil { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } + } + defer func() { + _ = tx.Done() + }() + + latestSequence, err := tx.GetLatestLedgerSequence() + if err != nil { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } + } + + latestLedger, found, err := h.ledgerReader.GetLedger(ctx, latestSequence) + if (err != nil) || (!found) { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } + } + + return GetTransactionsResponse{ + Transactions: txns, + LatestLedger: int64(latestLedger.LedgerSequence()), + LatestLedgerCloseTimestamp: int64(latestLedger.LedgerHeaderHistoryEntry().Header.ScpValue.CloseTime), + Pagination: &TransactionsPaginationOptions{ + Cursor: &cursor, + Limit: limit, + }, + }, nil - //for ledgerSeq := request.StartLedger; ledgerSeq <= request.EndLedger; ledgerSeq++ { - // ledger, found, err := h.ledgerReader.GetLedger(ctx, ledgerSeq) - // if (err != nil) || (!found) { - // return GetTransactionsResponse{}, &jrpc2.Error{ - // Code: jrpc2.InternalError, - // Message: "could not get ledger sequence", - // } - // } - // - // txCount := ledger.CountTransactions() - // for i := 0; i < txCount; i++ { - // - // } - // - //} } -func NewGetTransactionsHandler(logger *log.Entry, ledgerReader db.LedgerReader, ledgerEntryReader db.LedgerEntryReader, maxLimit, defaultLimit uint) jrpc2.Handler { +func NewGetTransactionsHandler(logger *log.Entry, ledgerReader db.LedgerReader, ledgerEntryReader db.LedgerEntryReader, maxLimit, defaultLimit uint, networkPassphrase string) jrpc2.Handler { transactionsHandler := transactionsRPCHandler{ ledgerReader: ledgerReader, ledgerEntryReader: ledgerEntryReader, maxLimit: maxLimit, defaultLimit: defaultLimit, logger: logger, + networkPassphrase: networkPassphrase, } return handler.New(func(context context.Context, request GetTransactionsRequest) (GetTransactionsResponse, error) { diff --git a/cmd/soroban-rpc/internal/transactions/cursor.go b/cmd/soroban-rpc/internal/transactions/cursor.go index 14021d1d..8c1d2897 100644 --- a/cmd/soroban-rpc/internal/transactions/cursor.go +++ b/cmd/soroban-rpc/internal/transactions/cursor.go @@ -45,3 +45,11 @@ func (c Cursor) UnmarshalJSON(b []byte) error { func (c Cursor) Cmp(other interfaces.Cursor) int { return 0 } + +func NewCursor(sequence uint32, txIdx uint32, opIdx uint32) Cursor { + return Cursor{ + LedgerSequence: sequence, + TxIdx: txIdx, + OpIdx: opIdx, + } +} From 7928c783e65d3347651b5e4f1f9c481d5b1d1a48 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Mon, 15 Apr 2024 14:21:26 -0400 Subject: [PATCH 04/57] Add getLedgers --- cmd/soroban-rpc/internal/db/ledger.go | 13 ++++++++++++- cmd/soroban-rpc/internal/transactions/cursor.go | 15 +++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/cmd/soroban-rpc/internal/db/ledger.go b/cmd/soroban-rpc/internal/db/ledger.go index a8676aa2..3be9671e 100644 --- a/cmd/soroban-rpc/internal/db/ledger.go +++ b/cmd/soroban-rpc/internal/db/ledger.go @@ -71,7 +71,18 @@ func (r ledgerReader) GetLedger(ctx context.Context, sequence uint32) (xdr.Ledge } func (r ledgerReader) GetLedgers(ctx context.Context, startSequence uint32, endSequence uint32) ([]xdr.LedgerCloseMeta, error) { - return []xdr.LedgerCloseMeta{}, nil + sql := sq.Select("meta"). + From(ledgerCloseMetaTableName). + Where( + sq.And{ + sq.GtOrEq{"sequence": startSequence}, + sq.LtOrEq{"sequence": endSequence}, + }) + var results []xdr.LedgerCloseMeta + if err := r.db.Select(ctx, &results, sql); err != nil { + return []xdr.LedgerCloseMeta{}, err + } + return results, nil } type ledgerWriter struct { diff --git a/cmd/soroban-rpc/internal/transactions/cursor.go b/cmd/soroban-rpc/internal/transactions/cursor.go index 8c1d2897..c88e8dc7 100644 --- a/cmd/soroban-rpc/internal/transactions/cursor.go +++ b/cmd/soroban-rpc/internal/transactions/cursor.go @@ -43,6 +43,21 @@ func (c Cursor) UnmarshalJSON(b []byte) error { // 1 is returned if c is greater than other. // -1 is returned if c is less than other. func (c Cursor) Cmp(other interfaces.Cursor) int { + otherCursor := other.(*Cursor) + + if c.LedgerSequence == otherCursor.LedgerSequence { + return cmp(c.TxIdx, otherCursor.TxIdx) + } + return cmp(c.LedgerSequence, otherCursor.LedgerSequence) +} + +func cmp(a, b uint32) int { + if a < b { + return -1 + } + if a > b { + return 1 + } return 0 } From 355b1e2f2de0c2ee79507743f930de4058ee593e Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Mon, 15 Apr 2024 15:54:57 -0400 Subject: [PATCH 05/57] Read a single ledger instead of getting all ledgers --- cmd/soroban-rpc/internal/db/ledger.go | 30 ++++++------- .../internal/methods/get_transactions.go | 44 ++++++++++++------- 2 files changed, 42 insertions(+), 32 deletions(-) diff --git a/cmd/soroban-rpc/internal/db/ledger.go b/cmd/soroban-rpc/internal/db/ledger.go index 3be9671e..b67a4e66 100644 --- a/cmd/soroban-rpc/internal/db/ledger.go +++ b/cmd/soroban-rpc/internal/db/ledger.go @@ -17,7 +17,7 @@ type StreamLedgerFn func(xdr.LedgerCloseMeta) error type LedgerReader interface { GetLedger(ctx context.Context, sequence uint32) (xdr.LedgerCloseMeta, bool, error) - GetLedgers(ctx context.Context, startSequence uint32, endSequence uint32) ([]xdr.LedgerCloseMeta, error) + //GetLedgers(ctx context.Context, startSequence uint32, endSequence uint32) ([]xdr.LedgerCloseMeta, error) StreamAllLedgers(ctx context.Context, f StreamLedgerFn) error } @@ -70,20 +70,20 @@ func (r ledgerReader) GetLedger(ctx context.Context, sequence uint32) (xdr.Ledge } } -func (r ledgerReader) GetLedgers(ctx context.Context, startSequence uint32, endSequence uint32) ([]xdr.LedgerCloseMeta, error) { - sql := sq.Select("meta"). - From(ledgerCloseMetaTableName). - Where( - sq.And{ - sq.GtOrEq{"sequence": startSequence}, - sq.LtOrEq{"sequence": endSequence}, - }) - var results []xdr.LedgerCloseMeta - if err := r.db.Select(ctx, &results, sql); err != nil { - return []xdr.LedgerCloseMeta{}, err - } - return results, nil -} +//func (r ledgerReader) GetLedgers(ctx context.Context, startSequence uint32, endSequence uint32) ([]xdr.LedgerCloseMeta, error) { +// sql := sq.Select("meta"). +// From(ledgerCloseMetaTableName). +// Where( +// sq.And{ +// sq.GtOrEq{"sequence": startSequence}, +// sq.LtOrEq{"sequence": endSequence}, +// }) +// var results []xdr.LedgerCloseMeta +// if err := r.db.Select(ctx, &results, sql); err != nil { +// return []xdr.LedgerCloseMeta{}, err +// } +// return results, nil +//} type ledgerWriter struct { stmtCache *sq.StmtCache diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index bb780528..30571a1e 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -100,6 +100,9 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont start := transactions.NewCursor(request.StartLedger, 0, 0) endLedger, found, err := h.ledgerReader.GetLedger(ctx, request.EndLedger) if err != nil || !found { + if err == nil { + err = errors.New("ledger close meta not found") + } return GetTransactionsResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, Message: err.Error(), @@ -134,22 +137,25 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont } } - // Get all ledgers within the range from db - ledgers, err := h.ledgerReader.GetLedgers(ctx, ledgerRange.Start.LedgerSequence, ledgerRange.End.LedgerSequence) - if err != nil { - return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, - Message: err.Error(), - } - } - // Iterate through each ledger and its transactions until limit or end range is reached txns := make([]TransactionInfo, limit) var cursor transactions.Cursor - for _, lcm := range ledgers { + for ledgerSeq := ledgerRange.Start.LedgerSequence; ledgerSeq <= ledgerRange.End.LedgerSequence; ledgerSeq++ { + // Get ledger close meta from db + ledger, found, err := h.ledgerReader.GetLedger(ctx, ledgerSeq) + if (err != nil) || (!found) { + if err == nil { + err = errors.New("ledger close meta not found") + } + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } + } + // Build transaction envelopes in the ledger byHash := map[xdr.Hash]xdr.TransactionEnvelope{} - for _, tx := range lcm.TransactionEnvelopes() { + for _, tx := range ledger.TransactionEnvelopes() { hash, err := network.HashTransactionInEnvelope(tx, h.networkPassphrase) if err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ @@ -160,14 +166,15 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont byHash[hash] = tx } - txCount := lcm.CountTransactions() + // Decode transaction info from ledger meta + txCount := ledger.CountTransactions() for i := ledgerRange.Start.TxIdx; i < uint32(txCount); i++ { - cursor = transactions.NewCursor(lcm.LedgerSequence(), i, 0) + cursor = transactions.NewCursor(ledger.LedgerSequence(), i, 0) if ledgerRange.End.Cmp(cursor) <= 0 { break } - hash := lcm.TransactionHash(int(i)) + hash := ledger.TransactionHash(int(i)) envelope, ok := byHash[hash] if !ok { hexHash := hex.EncodeToString(hash[:]) @@ -177,14 +184,14 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont Message: err.Error(), } } - txResult := lcm.TransactionResultPair(int(i)) - unsafeMeta := lcm.TxApplyProcessing(int(i)) + txResult := ledger.TransactionResultPair(int(i)) + unsafeMeta := ledger.TxApplyProcessing(int(i)) txInfo := TransactionInfo{ FeeBump: envelope.IsFeeBump(), ApplicationOrder: int32(i + 1), Successful: txResult.Result.Successful(), - LedgerSequence: uint(lcm.LedgerSequence()), + LedgerSequence: uint(ledger.LedgerSequence()), } if txInfo.Result, err = txResult.Result.MarshalBinary(); err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ @@ -233,6 +240,9 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont latestLedger, found, err := h.ledgerReader.GetLedger(ctx, latestSequence) if (err != nil) || (!found) { + if err == nil { + err = errors.New("ledger close meta not found") + } return GetTransactionsResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, Message: err.Error(), From 11baf9e5d5f2afa7767583d513fa9dd0c98a908a Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Mon, 15 Apr 2024 16:21:23 -0400 Subject: [PATCH 06/57] Add ParseCursor method for tx cursor --- .../internal/daemon/interfaces/interfaces.go | 1 + cmd/soroban-rpc/internal/events/cursor.go | 25 ++++++++----- .../internal/transactions/cursor.go | 37 +++++++++++++++++-- 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/cmd/soroban-rpc/internal/daemon/interfaces/interfaces.go b/cmd/soroban-rpc/internal/daemon/interfaces/interfaces.go index c3b42148..672fb492 100644 --- a/cmd/soroban-rpc/internal/daemon/interfaces/interfaces.go +++ b/cmd/soroban-rpc/internal/daemon/interfaces/interfaces.go @@ -26,4 +26,5 @@ type Cursor interface { MarshalJSON() ([]byte, error) UnmarshalJSON(b []byte) error Cmp(other Cursor) int + ParseCursor(input string) (Cursor, error) } diff --git a/cmd/soroban-rpc/internal/events/cursor.go b/cmd/soroban-rpc/internal/events/cursor.go index 886d103d..87fbfbb7 100644 --- a/cmd/soroban-rpc/internal/events/cursor.go +++ b/cmd/soroban-rpc/internal/events/cursor.go @@ -30,7 +30,7 @@ type Cursor struct { } // String returns a string representation of this cursor -func (c Cursor) String() string { +func (c *Cursor) String() string { return fmt.Sprintf( "%019d-%010d", toid.New(int32(c.Ledger), int32(c.Tx), int32(c.Op)).ToInt64(), @@ -39,7 +39,7 @@ func (c Cursor) String() string { } // MarshalJSON marshals the cursor into JSON -func (c Cursor) MarshalJSON() ([]byte, error) { +func (c *Cursor) MarshalJSON() ([]byte, error) { return json.Marshal(c.String()) } @@ -50,35 +50,40 @@ func (c *Cursor) UnmarshalJSON(b []byte) error { return err } - if parsed, err := ParseCursor(s); err != nil { + parsed, err := c.ParseCursor(s) + if err != nil { return err + } + + if eventCursor, ok := parsed.(*Cursor); ok { + *c = *eventCursor } else { - *c = parsed + return fmt.Errorf("parsed cursor could not be converted to Event cursor") } return nil } // ParseCursor parses the given string and returns the corresponding cursor -func ParseCursor(input string) (Cursor, error) { +func (c *Cursor) ParseCursor(input string) (interfaces.Cursor, error) { parts := strings.SplitN(input, "-", 2) if len(parts) != 2 { - return Cursor{}, fmt.Errorf("invalid event id %s", input) + return &Cursor{}, fmt.Errorf("invalid event id %s", input) } // Parse the first part (toid) idInt, err := strconv.ParseInt(parts[0], 10, 64) //lint:ignore gomnd if err != nil { - return Cursor{}, fmt.Errorf("invalid event id %s: %w", input, err) + return &Cursor{}, fmt.Errorf("invalid event id %s: %w", input, err) } parsed := toid.Parse(idInt) // Parse the second part (event order) eventOrder, err := strconv.ParseUint(parts[1], 10, 32) //lint:ignore gomnd if err != nil { - return Cursor{}, fmt.Errorf("invalid event id %s: %w", input, err) + return &Cursor{}, fmt.Errorf("invalid event id %s: %w", input, err) } - return Cursor{ + return &Cursor{ Ledger: uint32(parsed.LedgerSequence), Tx: uint32(parsed.TransactionOrder), Op: uint32(parsed.OperationOrder), @@ -100,7 +105,7 @@ func cmp(a, b uint32) int { // 0 is returned if the c is equal to other. // 1 is returned if c is greater than other. // -1 is returned if c is less than other. -func (c Cursor) Cmp(other interfaces.Cursor) int { +func (c *Cursor) Cmp(other interfaces.Cursor) int { otherCursor := other.(*Cursor) if c.Ledger == otherCursor.Ledger { diff --git a/cmd/soroban-rpc/internal/transactions/cursor.go b/cmd/soroban-rpc/internal/transactions/cursor.go index c88e8dc7..adc9b53b 100644 --- a/cmd/soroban-rpc/internal/transactions/cursor.go +++ b/cmd/soroban-rpc/internal/transactions/cursor.go @@ -3,6 +3,7 @@ package transactions import ( "encoding/json" "fmt" + "strconv" "github.com/stellar/go/toid" @@ -21,7 +22,7 @@ type Cursor struct { } // String returns a string representation of this cursor -func (c Cursor) String() string { +func (c *Cursor) String() string { return fmt.Sprintf( "%019d", toid.New(int32(c.LedgerSequence), int32(c.TxIdx), int32(c.OpIdx)).ToInt64(), @@ -29,12 +30,27 @@ func (c Cursor) String() string { } // MarshalJSON marshals the cursor into JSON -func (c Cursor) MarshalJSON() ([]byte, error) { +func (c *Cursor) MarshalJSON() ([]byte, error) { return json.Marshal(c.String()) } // UnmarshalJSON unmarshalls a cursor from the given JSON -func (c Cursor) UnmarshalJSON(b []byte) error { +func (c *Cursor) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + + parsed, err := c.ParseCursor(s) + if err != nil { + return err + } + + if txCursor, ok := parsed.(*Cursor); ok { + *c = *txCursor + } else { + return fmt.Errorf("parsed cursor could not be converted to Transaction cursor") + } return nil } @@ -42,7 +58,7 @@ func (c Cursor) UnmarshalJSON(b []byte) error { // 0 is returned if the c is equal to other. // 1 is returned if c is greater than other. // -1 is returned if c is less than other. -func (c Cursor) Cmp(other interfaces.Cursor) int { +func (c *Cursor) Cmp(other interfaces.Cursor) int { otherCursor := other.(*Cursor) if c.LedgerSequence == otherCursor.LedgerSequence { @@ -51,6 +67,19 @@ func (c Cursor) Cmp(other interfaces.Cursor) int { return cmp(c.LedgerSequence, otherCursor.LedgerSequence) } +func (c *Cursor) ParseCursor(input string) (interfaces.Cursor, error) { + idInt, err := strconv.ParseInt(input, 10, 64) //lint:ignore gomnd + if err != nil { + return &Cursor{}, fmt.Errorf("invalid cursor %s: %w", input, err) + } + parsed := toid.Parse(idInt) + return &Cursor{ + LedgerSequence: uint32(parsed.LedgerSequence), + TxIdx: uint32(parsed.TransactionOrder), + OpIdx: uint32(parsed.OperationOrder), + }, nil +} + func cmp(a, b uint32) int { if a < b { return -1 From 81eceff8592eb4f338a08831296158b495409e59 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Mon, 15 Apr 2024 16:27:00 -0400 Subject: [PATCH 07/57] Cursor changes - 1 --- cmd/soroban-rpc/internal/events/cursor.go | 4 ++-- cmd/soroban-rpc/internal/methods/get_transactions.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/soroban-rpc/internal/events/cursor.go b/cmd/soroban-rpc/internal/events/cursor.go index 87fbfbb7..a1b6ba75 100644 --- a/cmd/soroban-rpc/internal/events/cursor.go +++ b/cmd/soroban-rpc/internal/events/cursor.go @@ -30,7 +30,7 @@ type Cursor struct { } // String returns a string representation of this cursor -func (c *Cursor) String() string { +func (c Cursor) String() string { return fmt.Sprintf( "%019d-%010d", toid.New(int32(c.Ledger), int32(c.Tx), int32(c.Op)).ToInt64(), @@ -105,7 +105,7 @@ func cmp(a, b uint32) int { // 0 is returned if the c is equal to other. // 1 is returned if c is greater than other. // -1 is returned if c is less than other. -func (c *Cursor) Cmp(other interfaces.Cursor) int { +func (c Cursor) Cmp(other interfaces.Cursor) int { otherCursor := other.(*Cursor) if c.Ledger == otherCursor.Ledger { diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 30571a1e..1b5f2086 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -170,7 +170,7 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont txCount := ledger.CountTransactions() for i := ledgerRange.Start.TxIdx; i < uint32(txCount); i++ { cursor = transactions.NewCursor(ledger.LedgerSequence(), i, 0) - if ledgerRange.End.Cmp(cursor) <= 0 { + if ledgerRange.End.Cmp(&cursor) <= 0 { break } From 83918f2f063fe6a7fb33090f3646dc6533c8f6a9 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Tue, 16 Apr 2024 11:51:29 -0400 Subject: [PATCH 08/57] Cursor changes - 2 --- .../internal/methods/get_transactions.go | 83 +++++-------------- 1 file changed, 20 insertions(+), 63 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 1b5f2086..68e64cba 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -28,26 +28,10 @@ type Range struct { End transactions.Cursor } -func (r Range) isValid(ctx context.Context, ledgerReader db.LedgerReader, ledgerEntryReader db.LedgerEntryReader) error { - //tx, err := ledgerEntryReader.NewTx(ctx) - //if err != nil { - // return errors.New("could not read transaction") - //} - //defer func() { - // _ = tx.Done() - //}() - // - //latestLedger, err := tx.GetLatestLedgerSequence() - //if err != nil { - // return errors.New("could not get latest ledger") - //} - return nil -} - type GetTransactionsRequest struct { - StartLedger uint32 - EndLedger uint32 - Pagination *TransactionsPaginationOptions + StartLedger uint32 `json:"startLedger"` + EndLedger uint32 `json:"endLedger"` + Pagination *TransactionsPaginationOptions `json:"pagination,omitempty"` } func (req GetTransactionsRequest) isValid() error { @@ -63,20 +47,20 @@ func (req GetTransactionsRequest) isValid() error { } type TransactionInfo struct { - Result []byte // XDR encoded xdr.TransactionResult - Meta []byte // XDR encoded xdr.TransactionMeta - Envelope []byte // XDR encoded xdr.TransactionEnvelope - FeeBump bool - ApplicationOrder int32 - Successful bool - LedgerSequence uint + Result []byte `json:"result"` + Meta []byte `json:"meta"` + Envelope []byte `json:"envelope"` + FeeBump bool `json:"feeBump"` + ApplicationOrder int32 `json:"applicationOrder"` + Successful bool `json:"successful"` + LedgerSequence uint `json:"ledgerSequence"` } type GetTransactionsResponse struct { - Transactions []TransactionInfo `json:"transactions"` - LatestLedger int64 `json:"latestLedger"` - LatestLedgerCloseTimestamp int64 `json:"latestLedgerCloseTimestamp"` - Pagination *TransactionsPaginationOptions + Transactions []TransactionInfo `json:"transactions"` + LatestLedger int64 `json:"latestLedger"` + LatestLedgerCloseTimestamp int64 `json:"latestLedgerCloseTimestamp"` + Pagination *TransactionsPaginationOptions `json:"pagination"` } type transactionsRPCHandler struct { @@ -97,20 +81,8 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont } } - start := transactions.NewCursor(request.StartLedger, 0, 0) - endLedger, found, err := h.ledgerReader.GetLedger(ctx, request.EndLedger) - if err != nil || !found { - if err == nil { - err = errors.New("ledger close meta not found") - } - return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, - Message: err.Error(), - } - } - end := transactions.NewCursor(request.EndLedger, uint32(endLedger.CountTransactions()), 0) - // Move start to pagination cursor + start := transactions.NewCursor(request.StartLedger, 0, 0) limit := h.defaultLimit if request.Pagination != nil { if request.Pagination.Cursor != nil { @@ -124,23 +96,11 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont } } - // Validate the range - ledgerRange := Range{ - Start: start, - End: end, - } - err = ledgerRange.isValid(ctx, h.ledgerReader, h.ledgerEntryReader) - if err != nil { - return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, - Message: err.Error(), - } - } - // Iterate through each ledger and its transactions until limit or end range is reached - txns := make([]TransactionInfo, limit) + var txns []TransactionInfo var cursor transactions.Cursor - for ledgerSeq := ledgerRange.Start.LedgerSequence; ledgerSeq <= ledgerRange.End.LedgerSequence; ledgerSeq++ { +LedgerLoop: + for ledgerSeq := request.StartLedger; ledgerSeq <= request.EndLedger; ledgerSeq++ { // Get ledger close meta from db ledger, found, err := h.ledgerReader.GetLedger(ctx, ledgerSeq) if (err != nil) || (!found) { @@ -168,11 +128,8 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont // Decode transaction info from ledger meta txCount := ledger.CountTransactions() - for i := ledgerRange.Start.TxIdx; i < uint32(txCount); i++ { + for i := start.TxIdx; i < uint32(txCount); i++ { cursor = transactions.NewCursor(ledger.LedgerSequence(), i, 0) - if ledgerRange.End.Cmp(&cursor) <= 0 { - break - } hash := ledger.TransactionHash(int(i)) envelope, ok := byHash[hash] @@ -214,7 +171,7 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont txns = append(txns, txInfo) if len(txns) >= int(limit) { - break + break LedgerLoop } } } From 3d7f7d3a5da2d85189794166886197b4221b9b48 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Tue, 16 Apr 2024 12:57:59 -0400 Subject: [PATCH 09/57] Cursor changes - 3 --- cmd/soroban-rpc/internal/db/transaction.go | 21 ----- .../internal/methods/get_transactions.go | 4 +- go.mod | 39 ++++---- go.sum | 94 +++++++++++-------- 4 files changed, 81 insertions(+), 77 deletions(-) delete mode 100644 cmd/soroban-rpc/internal/db/transaction.go diff --git a/cmd/soroban-rpc/internal/db/transaction.go b/cmd/soroban-rpc/internal/db/transaction.go deleted file mode 100644 index e0871fef..00000000 --- a/cmd/soroban-rpc/internal/db/transaction.go +++ /dev/null @@ -1,21 +0,0 @@ -package db - -type TransactionReader interface{} - -type transactionReader struct { - db *DB -} - -func NewTransactionReader(db *DB) TransactionReader { - return transactionReader{db: db} -} - -type TransactionWriter interface{} - -type transactionWriter struct { - db *DB -} - -func NewTransactionWriter(db *DB) TransactionWriter { - return transactionWriter{db: db} -} diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 68e64cba..35bb1450 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -87,7 +87,7 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont if request.Pagination != nil { if request.Pagination.Cursor != nil { start = *request.Pagination.Cursor - // increment event index because, when paginating, + // increment tx index because, when paginating, // we start with the item right after the cursor start.TxIdx++ } @@ -100,7 +100,7 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont var txns []TransactionInfo var cursor transactions.Cursor LedgerLoop: - for ledgerSeq := request.StartLedger; ledgerSeq <= request.EndLedger; ledgerSeq++ { + for ledgerSeq := start.LedgerSequence; ledgerSeq <= request.EndLedger; ledgerSeq++ { // Get ledger close meta from db ledger, found, err := h.ledgerReader.GetLedger(ctx, ledgerSeq) if (err != nil) || (!found) { diff --git a/go.mod b/go.mod index b81f67ed..b383560c 100644 --- a/go.mod +++ b/go.mod @@ -18,26 +18,28 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - github.com/stellar/go v0.0.0-20240207003209-73de95c8eb55 + github.com/stellar/go v0.0.0-20240416162339-73233da7c30e github.com/stretchr/testify v1.8.4 golang.org/x/mod v0.13.0 ) require ( - cloud.google.com/go v0.111.0 // indirect + cloud.google.com/go v0.112.0 // indirect cloud.google.com/go/compute v1.23.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v1.1.5 // indirect - cloud.google.com/go/storage v1.30.1 // indirect + cloud.google.com/go/storage v1.37.0 // indirect dario.cat/mergo v1.0.0 // indirect github.com/cloudflare/circl v1.3.5 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/djherbis/fscache v0.10.1 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/s2a-go v0.1.7 // indirect - github.com/google/uuid v1.4.0 // indirect + github.com/google/uuid v1.5.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect @@ -50,18 +52,23 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/otel v1.19.0 // indirect - go.opentelemetry.io/otel/metric v1.19.0 // indirect - go.opentelemetry.io/otel/trace v1.19.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect + go.opentelemetry.io/otel v1.21.0 // indirect + go.opentelemetry.io/otel/metric v1.21.0 // indirect + go.opentelemetry.io/otel/trace v1.21.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/oauth2 v0.13.0 // indirect + golang.org/x/oauth2 v0.16.0 // indirect + golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.14.0 // indirect - google.golang.org/api v0.149.0 // indirect + google.golang.org/api v0.157.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20231211222908-989df2bf70f3 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240122161410-6c6643bf1457 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect google.golang.org/grpc v1.60.1 // indirect + gopkg.in/djherbis/atime.v1 v1.0.0 // indirect + gopkg.in/djherbis/stream.v1 v1.3.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) @@ -106,10 +113,10 @@ require ( github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2 // indirect github.com/stretchr/objx v0.5.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.16.0 // indirect + golang.org/x/crypto v0.18.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/sync v0.5.0 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sync v0.6.0 // indirect golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect google.golang.org/protobuf v1.32.0 // indirect diff --git a/go.sum b/go.sum index 4cd67af2..2cd276e2 100644 --- a/go.sum +++ b/go.sum @@ -17,8 +17,8 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.111.0 h1:YHLKNupSD1KqjDbQ3+LVdQ81h/UJbJyZG203cEfnQgM= -cloud.google.com/go v0.111.0/go.mod h1:0mibmpKP1TyOOFYQY5izo0LnT+ecvOQ0Sg3OdmMiNRU= +cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= +cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -43,8 +43,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM= -cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= +cloud.google.com/go/storage v1.37.0 h1:WI8CsaFO8Q9KjPVtsZ5Cmi0dXV25zMoX0FklT7c3Jm4= +cloud.google.com/go/storage v1.37.0/go.mod h1:i34TiT2IhiNDmcj65PqwCjcoUX7Z5pLzS8DEmoiFq1k= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -91,6 +91,8 @@ github.com/cloudflare/circl v1.3.5/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUK github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creachadair/jrpc2 v1.1.2 h1:UOYMipEFYlwd5qmcvs9GZBurn3oXt1UDIX5JLjWWFzo= github.com/creachadair/jrpc2 v1.1.2/go.mod h1:JcCe2Eny3lIvVwZLm92WXyU+tNUgTBWFCLMsfNkjEGk= @@ -102,6 +104,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/djherbis/fscache v0.10.1 h1:hDv+RGyvD+UDKyRYuLoVNbuRTnf2SrA2K3VyR1br9lk= +github.com/djherbis/fscache v0.10.1/go.mod h1:yyPYtkNnnPXsW+81lAcQS6yab3G2CRfnPLotBvtbf0c= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= @@ -112,8 +116,12 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/fatih/structs v1.0.0 h1:BrX964Rv5uQ3wwS+KRUAJCBBw5PQmgJfJ6v4yly5QwU= github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= @@ -142,8 +150,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2 github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= @@ -222,8 +230,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -364,8 +372,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= -github.com/stellar/go v0.0.0-20240207003209-73de95c8eb55 h1:YBpAp7uPf/lzGxKPOGh1D05bX7uDVybA39BYoPXpRu4= -github.com/stellar/go v0.0.0-20240207003209-73de95c8eb55/go.mod h1:Ka4piwZT4Q9799f+BZeaKkAiYo4UpIWXyu0oSUbCVfM= +github.com/stellar/go v0.0.0-20240416162339-73233da7c30e h1:nqiU0AQQi+y8jyAPqG9Hk+JPPxOojcwLhcuK63Sq1pU= +github.com/stellar/go v0.0.0-20240416162339-73233da7c30e/go.mod h1:ckzsX0B0qfTMVZQJtPELJLs7cJ6xXMYHPVLyIsReGsU= github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2 h1:OzCVd0SV5qE3ZcDeSFCmOWLZfEWZ3Oe8KtmSOYKEVWE= github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2/go.mod h1:yoxyU/M8nl9LKeWIoBrbDPQ7Cy+4jxRcWcOayZ4BMps= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -418,14 +426,18 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= -go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= -go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= -go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= -go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= -go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= -go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= -go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= +go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= +go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= +go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= +go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= +go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -439,8 +451,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -518,8 +530,8 @@ golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -529,8 +541,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= -golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -543,8 +555,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -599,8 +611,8 @@ golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -618,6 +630,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -673,8 +687,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -694,8 +708,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.149.0 h1:b2CqT6kG+zqJIVKRQ3ELJVLN1PwHZ6DJ3dW8yl82rgY= -google.golang.org/api v0.149.0/go.mod h1:Mwn1B7JTXrzXtnvmzQE2BD6bYZQ8DShKZDZbeN9I7qI= +google.golang.org/api v0.157.0 h1:ORAeqmbrrozeyw5NjnMxh7peHO0UzV4wWYSwZeCUb20= +google.golang.org/api v0.157.0/go.mod h1:+z4v4ufbZ1WEpld6yMGHyggs+PmAHiaLNj5ytP3N01g= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -741,12 +755,12 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos= -google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY= -google.golang.org/genproto/googleapis/api v0.0.0-20231211222908-989df2bf70f3 h1:EWIeHfGuUf00zrVZGEgYFxok7plSAXBGcH7NNdMAWvA= -google.golang.org/genproto/googleapis/api v0.0.0-20231211222908-989df2bf70f3/go.mod h1:k2dtGpRrbsSyKcNPKKI5sstZkrNCZwpU/ns96JoHbGg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= +google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg= +google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k= +google.golang.org/genproto/googleapis/api v0.0.0-20240122161410-6c6643bf1457 h1:KHBtwE+eQc3+NxpjmRFlQ3pJQ2FNnhhgB9xOV8kyBuU= +google.golang.org/genproto/googleapis/api v0.0.0-20240122161410-6c6643bf1457/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac h1:nUQEQmH/csSvFECKYRv6HWEyypysidKl2I6Qpsglq/0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -784,6 +798,10 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/djherbis/atime.v1 v1.0.0 h1:eMRqB/JrLKocla2PBPKgQYg/p5UG4L6AUAs92aP7F60= +gopkg.in/djherbis/atime.v1 v1.0.0/go.mod h1:hQIUStKmJfvf7xdh/wtK84qe+DsTV5LnA9lzxxtPpJ8= +gopkg.in/djherbis/stream.v1 v1.3.1 h1:uGfmsOY1qqMjQQphhRBSGLyA9qumJ56exkRu9ASTjCw= +gopkg.in/djherbis/stream.v1 v1.3.1/go.mod h1:aEV8CBVRmSpLamVJfM903Npic1IKmb2qS30VAZ+sssg= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/gavv/httpexpect.v1 v1.0.0-20170111145843-40724cf1e4a0 h1:r5ptJ1tBxVAeqw4CrYWhXIMr0SybY3CDHuIbCg5CFVw= gopkg.in/gavv/httpexpect.v1 v1.0.0-20170111145843-40724cf1e4a0/go.mod h1:WtiW9ZA1LdaWqtQRo1VbIL/v4XZ8NDta+O/kSpGgVek= From f50945799e577fee08894c156d22ca0429378ad8 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Tue, 16 Apr 2024 13:10:00 -0400 Subject: [PATCH 10/57] revert go-mod changes --- go.mod | 39 ++++++++++-------------- go.sum | 94 ++++++++++++++++++++++++---------------------------------- 2 files changed, 54 insertions(+), 79 deletions(-) diff --git a/go.mod b/go.mod index b383560c..b81f67ed 100644 --- a/go.mod +++ b/go.mod @@ -18,28 +18,26 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - github.com/stellar/go v0.0.0-20240416162339-73233da7c30e + github.com/stellar/go v0.0.0-20240207003209-73de95c8eb55 github.com/stretchr/testify v1.8.4 golang.org/x/mod v0.13.0 ) require ( - cloud.google.com/go v0.112.0 // indirect + cloud.google.com/go v0.111.0 // indirect cloud.google.com/go/compute v1.23.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v1.1.5 // indirect - cloud.google.com/go/storage v1.37.0 // indirect + cloud.google.com/go/storage v1.30.1 // indirect dario.cat/mergo v1.0.0 // indirect github.com/cloudflare/circl v1.3.5 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect - github.com/djherbis/fscache v0.10.1 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/s2a-go v0.1.7 // indirect - github.com/google/uuid v1.5.0 // indirect + github.com/google/uuid v1.4.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect @@ -52,23 +50,18 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect - go.opentelemetry.io/otel v1.21.0 // indirect - go.opentelemetry.io/otel/metric v1.21.0 // indirect - go.opentelemetry.io/otel/trace v1.21.0 // indirect + go.opentelemetry.io/otel v1.19.0 // indirect + go.opentelemetry.io/otel/metric v1.19.0 // indirect + go.opentelemetry.io/otel/trace v1.19.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/oauth2 v0.16.0 // indirect - golang.org/x/time v0.5.0 // indirect + golang.org/x/oauth2 v0.13.0 // indirect golang.org/x/tools v0.14.0 // indirect - google.golang.org/api v0.157.0 // indirect + google.golang.org/api v0.149.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240122161410-6c6643bf1457 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect + google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231211222908-989df2bf70f3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect google.golang.org/grpc v1.60.1 // indirect - gopkg.in/djherbis/atime.v1 v1.0.0 // indirect - gopkg.in/djherbis/stream.v1 v1.3.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) @@ -113,10 +106,10 @@ require ( github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2 // indirect github.com/stretchr/objx v0.5.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.18.0 // indirect + golang.org/x/crypto v0.16.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/sync v0.6.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sync v0.5.0 // indirect golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect google.golang.org/protobuf v1.32.0 // indirect diff --git a/go.sum b/go.sum index 2cd276e2..4cd67af2 100644 --- a/go.sum +++ b/go.sum @@ -17,8 +17,8 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= -cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= +cloud.google.com/go v0.111.0 h1:YHLKNupSD1KqjDbQ3+LVdQ81h/UJbJyZG203cEfnQgM= +cloud.google.com/go v0.111.0/go.mod h1:0mibmpKP1TyOOFYQY5izo0LnT+ecvOQ0Sg3OdmMiNRU= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -43,8 +43,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.37.0 h1:WI8CsaFO8Q9KjPVtsZ5Cmi0dXV25zMoX0FklT7c3Jm4= -cloud.google.com/go/storage v1.37.0/go.mod h1:i34TiT2IhiNDmcj65PqwCjcoUX7Z5pLzS8DEmoiFq1k= +cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM= +cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -91,8 +91,6 @@ github.com/cloudflare/circl v1.3.5/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUK github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creachadair/jrpc2 v1.1.2 h1:UOYMipEFYlwd5qmcvs9GZBurn3oXt1UDIX5JLjWWFzo= github.com/creachadair/jrpc2 v1.1.2/go.mod h1:JcCe2Eny3lIvVwZLm92WXyU+tNUgTBWFCLMsfNkjEGk= @@ -104,8 +102,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/djherbis/fscache v0.10.1 h1:hDv+RGyvD+UDKyRYuLoVNbuRTnf2SrA2K3VyR1br9lk= -github.com/djherbis/fscache v0.10.1/go.mod h1:yyPYtkNnnPXsW+81lAcQS6yab3G2CRfnPLotBvtbf0c= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= @@ -116,12 +112,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= -github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/fatih/structs v1.0.0 h1:BrX964Rv5uQ3wwS+KRUAJCBBw5PQmgJfJ6v4yly5QwU= github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= @@ -150,8 +142,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2 github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= @@ -230,8 +222,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= -github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -372,8 +364,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= -github.com/stellar/go v0.0.0-20240416162339-73233da7c30e h1:nqiU0AQQi+y8jyAPqG9Hk+JPPxOojcwLhcuK63Sq1pU= -github.com/stellar/go v0.0.0-20240416162339-73233da7c30e/go.mod h1:ckzsX0B0qfTMVZQJtPELJLs7cJ6xXMYHPVLyIsReGsU= +github.com/stellar/go v0.0.0-20240207003209-73de95c8eb55 h1:YBpAp7uPf/lzGxKPOGh1D05bX7uDVybA39BYoPXpRu4= +github.com/stellar/go v0.0.0-20240207003209-73de95c8eb55/go.mod h1:Ka4piwZT4Q9799f+BZeaKkAiYo4UpIWXyu0oSUbCVfM= github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2 h1:OzCVd0SV5qE3ZcDeSFCmOWLZfEWZ3Oe8KtmSOYKEVWE= github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2/go.mod h1:yoxyU/M8nl9LKeWIoBrbDPQ7Cy+4jxRcWcOayZ4BMps= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -426,18 +418,14 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= -go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= -go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= +go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= +go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= +go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= +go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -451,8 +439,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -530,8 +518,8 @@ golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -541,8 +529,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -555,8 +543,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -611,8 +599,8 @@ golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -630,8 +618,6 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -687,8 +673,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -708,8 +694,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.157.0 h1:ORAeqmbrrozeyw5NjnMxh7peHO0UzV4wWYSwZeCUb20= -google.golang.org/api v0.157.0/go.mod h1:+z4v4ufbZ1WEpld6yMGHyggs+PmAHiaLNj5ytP3N01g= +google.golang.org/api v0.149.0 h1:b2CqT6kG+zqJIVKRQ3ELJVLN1PwHZ6DJ3dW8yl82rgY= +google.golang.org/api v0.149.0/go.mod h1:Mwn1B7JTXrzXtnvmzQE2BD6bYZQ8DShKZDZbeN9I7qI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -755,12 +741,12 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg= -google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k= -google.golang.org/genproto/googleapis/api v0.0.0-20240122161410-6c6643bf1457 h1:KHBtwE+eQc3+NxpjmRFlQ3pJQ2FNnhhgB9xOV8kyBuU= -google.golang.org/genproto/googleapis/api v0.0.0-20240122161410-6c6643bf1457/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac h1:nUQEQmH/csSvFECKYRv6HWEyypysidKl2I6Qpsglq/0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY= +google.golang.org/genproto/googleapis/api v0.0.0-20231211222908-989df2bf70f3 h1:EWIeHfGuUf00zrVZGEgYFxok7plSAXBGcH7NNdMAWvA= +google.golang.org/genproto/googleapis/api v0.0.0-20231211222908-989df2bf70f3/go.mod h1:k2dtGpRrbsSyKcNPKKI5sstZkrNCZwpU/ns96JoHbGg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -798,10 +784,6 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/djherbis/atime.v1 v1.0.0 h1:eMRqB/JrLKocla2PBPKgQYg/p5UG4L6AUAs92aP7F60= -gopkg.in/djherbis/atime.v1 v1.0.0/go.mod h1:hQIUStKmJfvf7xdh/wtK84qe+DsTV5LnA9lzxxtPpJ8= -gopkg.in/djherbis/stream.v1 v1.3.1 h1:uGfmsOY1qqMjQQphhRBSGLyA9qumJ56exkRu9ASTjCw= -gopkg.in/djherbis/stream.v1 v1.3.1/go.mod h1:aEV8CBVRmSpLamVJfM903Npic1IKmb2qS30VAZ+sssg= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/gavv/httpexpect.v1 v1.0.0-20170111145843-40724cf1e4a0 h1:r5ptJ1tBxVAeqw4CrYWhXIMr0SybY3CDHuIbCg5CFVw= gopkg.in/gavv/httpexpect.v1 v1.0.0-20170111145843-40724cf1e4a0/go.mod h1:WtiW9ZA1LdaWqtQRo1VbIL/v4XZ8NDta+O/kSpGgVek= From f813d0131bc5f7f8d0a2f4b646ad5bf671c3cb01 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Tue, 16 Apr 2024 13:34:41 -0400 Subject: [PATCH 11/57] Use reader.Seek() --- .../internal/methods/get_transactions.go | 48 +++++++++---------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 35bb1450..09ba061d 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -2,14 +2,12 @@ package methods import ( "context" - "encoding/hex" "github.com/creachadair/jrpc2" "github.com/creachadair/jrpc2/handler" - "github.com/stellar/go/network" + "github.com/stellar/go/ingest" "github.com/stellar/go/support/errors" "github.com/stellar/go/support/log" - "github.com/stellar/go/xdr" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/db" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/transactions" @@ -113,17 +111,20 @@ LedgerLoop: } } - // Build transaction envelopes in the ledger - byHash := map[xdr.Hash]xdr.TransactionEnvelope{} - for _, tx := range ledger.TransactionEnvelopes() { - hash, err := network.HashTransactionInEnvelope(tx, h.networkPassphrase) - if err != nil { - return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, - Message: err.Error(), - } + // Initialise tx reader and move it to start idx. + reader, err := ingest.NewLedgerTransactionReaderFromLedgerCloseMeta(h.networkPassphrase, ledger) + if err != nil { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } + } + err = reader.Seek(int(start.TxIdx)) + if err != nil { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), } - byHash[hash] = tx } // Decode transaction info from ledger meta @@ -131,38 +132,33 @@ LedgerLoop: for i := start.TxIdx; i < uint32(txCount); i++ { cursor = transactions.NewCursor(ledger.LedgerSequence(), i, 0) - hash := ledger.TransactionHash(int(i)) - envelope, ok := byHash[hash] - if !ok { - hexHash := hex.EncodeToString(hash[:]) - err = errors.Errorf("unknown tx hash in LedgerCloseMeta: %v", hexHash) + tx, err := reader.Read() + if err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, Message: err.Error(), } } - txResult := ledger.TransactionResultPair(int(i)) - unsafeMeta := ledger.TxApplyProcessing(int(i)) txInfo := TransactionInfo{ - FeeBump: envelope.IsFeeBump(), - ApplicationOrder: int32(i + 1), - Successful: txResult.Result.Successful(), + FeeBump: tx.Envelope.IsFeeBump(), + ApplicationOrder: int32(tx.Index), + Successful: tx.Result.Result.Successful(), LedgerSequence: uint(ledger.LedgerSequence()), } - if txInfo.Result, err = txResult.Result.MarshalBinary(); err != nil { + if txInfo.Result, err = tx.Result.Result.MarshalBinary(); err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, Message: err.Error(), } } - if txInfo.Meta, err = unsafeMeta.MarshalBinary(); err != nil { + if txInfo.Meta, err = tx.UnsafeMeta.MarshalBinary(); err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, Message: err.Error(), } } - if txInfo.Envelope, err = envelope.MarshalBinary(); err != nil { + if txInfo.Envelope, err = tx.Envelope.MarshalBinary(); err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, Message: err.Error(), From 0e8b9da0b62077510d0c131062f701356dffdcac Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Tue, 16 Apr 2024 14:28:49 -0400 Subject: [PATCH 12/57] Use reader.Seek() - 2 --- .../internal/methods/get_transactions.go | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 09ba061d..e5b764a6 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -111,7 +111,7 @@ LedgerLoop: } } - // Initialise tx reader and move it to start idx. + // Initialise tx reader. reader, err := ingest.NewLedgerTransactionReaderFromLedgerCloseMeta(h.networkPassphrase, ledger) if err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ @@ -119,18 +119,22 @@ LedgerLoop: Message: err.Error(), } } - err = reader.Seek(int(start.TxIdx)) + + // Move the reader to specific tx idx + startTxIdx := 0 + if ledgerSeq == start.LedgerSequence { + startTxIdx = int(start.TxIdx) + } + err = reader.Seek(startTxIdx) if err != nil { - return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, - Message: err.Error(), - } + // Seek returns EOF so we can move onto next ledger + continue } // Decode transaction info from ledger meta txCount := ledger.CountTransactions() - for i := start.TxIdx; i < uint32(txCount); i++ { - cursor = transactions.NewCursor(ledger.LedgerSequence(), i, 0) + for i := startTxIdx; i < txCount; i++ { + cursor = transactions.NewCursor(ledger.LedgerSequence(), uint32(i), 0) tx, err := reader.Read() if err != nil { From 5156b9ea0ad55674b4527a5c6a1b7cdda9efe31f Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Tue, 16 Apr 2024 14:35:17 -0400 Subject: [PATCH 13/57] Add config-options for tx pagination limits --- cmd/soroban-rpc/internal/config/options.go | 22 +++++++++++++++++++ .../internal/methods/get_transactions.go | 8 ------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/cmd/soroban-rpc/internal/config/options.go b/cmd/soroban-rpc/internal/config/options.go index df503200..d9099dd4 100644 --- a/cmd/soroban-rpc/internal/config/options.go +++ b/cmd/soroban-rpc/internal/config/options.go @@ -247,6 +247,28 @@ func (cfg *Config) options() ConfigOptions { return nil }, }, + { + Name: "max-transactions-limit", + Usage: "Maximum amount of transactions allowed in a single getTransactions response", + ConfigKey: &cfg.MaxTransactionsLimit, + DefaultValue: uint(10000), + }, + { + Name: "default-transactions-limit", + Usage: "Default cap on the amount of transactions included in a single getTransactions response", + ConfigKey: &cfg.DefaultTransactionsLimit, + DefaultValue: uint(100), + Validate: func(co *ConfigOption) error { + if cfg.DefaultTransactionsLimit > cfg.MaxTransactionsLimit { + return fmt.Errorf( + "default-transactions-limit (%v) cannot exceed max-transactions-limit (%v)", + cfg.DefaultTransactionsLimit, + cfg.MaxTransactionsLimit, + ) + } + return nil + }, + }, { Name: "max-healthy-ledger-latency", Usage: "maximum ledger latency (i.e. time elapsed since the last known ledger closing time) considered to be healthy" + diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index e5b764a6..4a78bee6 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -18,14 +18,6 @@ type TransactionsPaginationOptions struct { Limit uint `json:"limit,omitempty"` } -// Range defines a [Start, End] interval of ledgers. -type Range struct { - // Start defines the (inclusive) start of the range. - Start transactions.Cursor - // End defines the (inclusive) end of the range. - End transactions.Cursor -} - type GetTransactionsRequest struct { StartLedger uint32 `json:"startLedger"` EndLedger uint32 `json:"endLedger"` From 35da2a5f8e3fb3f27f3b3d3b95b98f6c40efba00 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Tue, 16 Apr 2024 14:55:34 -0400 Subject: [PATCH 14/57] Fix failing cursor test --- cmd/soroban-rpc/internal/events/cursor_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/soroban-rpc/internal/events/cursor_test.go b/cmd/soroban-rpc/internal/events/cursor_test.go index 6dfe1e58..1c16f64b 100644 --- a/cmd/soroban-rpc/internal/events/cursor_test.go +++ b/cmd/soroban-rpc/internal/events/cursor_test.go @@ -9,7 +9,7 @@ import ( ) func TestParseCursor(t *testing.T) { - for _, cursor := range []Cursor{ + for _, cursor := range []*Cursor{ { Ledger: math.MaxInt32, Tx: 1048575, @@ -29,7 +29,7 @@ func TestParseCursor(t *testing.T) { Event: 1, }, } { - parsed, err := ParseCursor(cursor.String()) + parsed, err := cursor.ParseCursor(cursor.String()) assert.NoError(t, err) assert.Equal(t, cursor, parsed) } @@ -97,12 +97,12 @@ func TestCursorCmp(t *testing.T) { b := testCase.b expected := testCase.expected - if got := a.Cmp(b); got != expected { + if got := a.Cmp(&b); got != expected { t.Fatalf("expected (%v).Cmp(%v) to be %v but got %v", a, b, expected, got) } a, b = b, a expected *= -1 - if got := a.Cmp(b); got != expected { + if got := a.Cmp(&b); got != expected { t.Fatalf("expected (%v).Cmp(%v) to be %v but got %v", a, b, expected, got) } } From 35ed84d8187a1f74d3f16d17cdbceccc3e887548 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Tue, 16 Apr 2024 14:59:37 -0400 Subject: [PATCH 15/57] Go mod changes --- .../internal/methods/get_transactions.go | 58 ++++++----- go.mod | 41 ++++---- go.sum | 98 +++++++++++-------- 3 files changed, 118 insertions(+), 79 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 4a78bee6..5395d9e2 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -2,6 +2,7 @@ package methods import ( "context" + "fmt" "github.com/creachadair/jrpc2" "github.com/creachadair/jrpc2/handler" @@ -24,7 +25,7 @@ type GetTransactionsRequest struct { Pagination *TransactionsPaginationOptions `json:"pagination,omitempty"` } -func (req GetTransactionsRequest) isValid() error { +func (req *GetTransactionsRequest) isValid(maxLimit uint) error { // Validate the start and end ledger sequence if req.StartLedger < 0 { return errors.New("start ledger cannot be negative") @@ -33,6 +34,16 @@ func (req GetTransactionsRequest) isValid() error { return errors.New("end ledger cannot be less than start ledger") } + // Validate pagination + if req.Pagination != nil && req.Pagination.Cursor != nil { + if req.StartLedger != 0 { + return errors.New("startLedger and cursor cannot both be set") + } + } + if req.Pagination != nil && req.Pagination.Limit > maxLimit { + return fmt.Errorf("limit must not exceed %d", maxLimit) + } + return nil } @@ -62,8 +73,8 @@ type transactionsRPCHandler struct { networkPassphrase string } -func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Context, request GetTransactionsRequest) (GetTransactionsResponse, error) { - err := request.isValid() +func (h *transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Context, request GetTransactionsRequest) (GetTransactionsResponse, error) { + err := request.isValid(h.maxLimit) if err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, @@ -168,23 +179,38 @@ LedgerLoop: } } - tx, err := h.ledgerEntryReader.NewTx(ctx) + latestLedgerSequence, latestLedgerCloseTime, err := h.getLatestLedgerDetails(ctx) if err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, Message: err.Error(), } } + + return GetTransactionsResponse{ + Transactions: txns, + LatestLedger: latestLedgerSequence, + LatestLedgerCloseTimestamp: latestLedgerCloseTime, + Pagination: &TransactionsPaginationOptions{ + Cursor: &cursor, + Limit: limit, + }, + }, nil + +} + +func (h *transactionsRPCHandler) getLatestLedgerDetails(ctx context.Context) (sequence int64, ledgerCloseTime int64, err error) { + tx, err := h.ledgerEntryReader.NewTx(ctx) + if err != nil { + return 0, 0, err + } defer func() { _ = tx.Done() }() latestSequence, err := tx.GetLatestLedgerSequence() if err != nil { - return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, - Message: err.Error(), - } + return 0, 0, err } latestLedger, found, err := h.ledgerReader.GetLedger(ctx, latestSequence) @@ -192,22 +218,10 @@ LedgerLoop: if err == nil { err = errors.New("ledger close meta not found") } - return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, - Message: err.Error(), - } + return 0, 0, err } - return GetTransactionsResponse{ - Transactions: txns, - LatestLedger: int64(latestLedger.LedgerSequence()), - LatestLedgerCloseTimestamp: int64(latestLedger.LedgerHeaderHistoryEntry().Header.ScpValue.CloseTime), - Pagination: &TransactionsPaginationOptions{ - Cursor: &cursor, - Limit: limit, - }, - }, nil - + return int64(latestLedger.LedgerSequence()), int64(latestLedger.LedgerHeaderHistoryEntry().Header.ScpValue.CloseTime), nil } func NewGetTransactionsHandler(logger *log.Entry, ledgerReader db.LedgerReader, ledgerEntryReader db.LedgerEntryReader, maxLimit, defaultLimit uint, networkPassphrase string) jrpc2.Handler { diff --git a/go.mod b/go.mod index 793453c6..b383560c 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ toolchain go1.22.1 require ( github.com/Masterminds/squirrel v1.5.4 github.com/cenkalti/backoff/v4 v4.2.1 - github.com/creachadair/jrpc2 v1.2.0 + github.com/creachadair/jrpc2 v1.1.2 github.com/go-chi/chi v4.1.2+incompatible github.com/go-git/go-git/v5 v5.9.0 github.com/mattn/go-sqlite3 v1.14.17 @@ -18,26 +18,28 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - github.com/stellar/go v0.0.0-20240207003209-73de95c8eb55 + github.com/stellar/go v0.0.0-20240416162339-73233da7c30e github.com/stretchr/testify v1.8.4 golang.org/x/mod v0.13.0 ) require ( - cloud.google.com/go v0.111.0 // indirect + cloud.google.com/go v0.112.0 // indirect cloud.google.com/go/compute v1.23.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v1.1.5 // indirect - cloud.google.com/go/storage v1.30.1 // indirect + cloud.google.com/go/storage v1.37.0 // indirect dario.cat/mergo v1.0.0 // indirect github.com/cloudflare/circl v1.3.5 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/djherbis/fscache v0.10.1 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/s2a-go v0.1.7 // indirect - github.com/google/uuid v1.4.0 // indirect + github.com/google/uuid v1.5.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect @@ -50,18 +52,23 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/otel v1.19.0 // indirect - go.opentelemetry.io/otel/metric v1.19.0 // indirect - go.opentelemetry.io/otel/trace v1.19.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect + go.opentelemetry.io/otel v1.21.0 // indirect + go.opentelemetry.io/otel/metric v1.21.0 // indirect + go.opentelemetry.io/otel/trace v1.21.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/oauth2 v0.13.0 // indirect + golang.org/x/oauth2 v0.16.0 // indirect + golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.14.0 // indirect - google.golang.org/api v0.149.0 // indirect + google.golang.org/api v0.157.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20231211222908-989df2bf70f3 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240122161410-6c6643bf1457 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect google.golang.org/grpc v1.60.1 // indirect + gopkg.in/djherbis/atime.v1 v1.0.0 // indirect + gopkg.in/djherbis/stream.v1 v1.3.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) @@ -74,7 +81,7 @@ require ( github.com/aws/aws-sdk-go v1.45.27 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/creachadair/mds v0.13.4 // indirect + github.com/creachadair/mds v0.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect @@ -106,9 +113,9 @@ require ( github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2 // indirect github.com/stretchr/objx v0.5.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.16.0 // indirect + golang.org/x/crypto v0.18.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect - golang.org/x/net v0.19.0 // indirect + golang.org/x/net v0.20.0 // indirect golang.org/x/sync v0.6.0 // indirect golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect diff --git a/go.sum b/go.sum index a5083ee2..2cd276e2 100644 --- a/go.sum +++ b/go.sum @@ -17,8 +17,8 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.111.0 h1:YHLKNupSD1KqjDbQ3+LVdQ81h/UJbJyZG203cEfnQgM= -cloud.google.com/go v0.111.0/go.mod h1:0mibmpKP1TyOOFYQY5izo0LnT+ecvOQ0Sg3OdmMiNRU= +cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= +cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -43,8 +43,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM= -cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= +cloud.google.com/go/storage v1.37.0 h1:WI8CsaFO8Q9KjPVtsZ5Cmi0dXV25zMoX0FklT7c3Jm4= +cloud.google.com/go/storage v1.37.0/go.mod h1:i34TiT2IhiNDmcj65PqwCjcoUX7Z5pLzS8DEmoiFq1k= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -91,17 +91,21 @@ github.com/cloudflare/circl v1.3.5/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUK github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creachadair/jrpc2 v1.2.0 h1:SXr0OgnwM0X18P+HccJP0uT3KGSDk/BCSRlJBvE2bMY= -github.com/creachadair/jrpc2 v1.2.0/go.mod h1:66uKSdr6tR5ZeNvkIjDSbbVUtOv0UhjS/vcd8ECP7Iw= -github.com/creachadair/mds v0.13.4 h1:RgU0MhiVqkzp6/xtNWhK6Pw7tDeaVuGFtA0UA2RBYvY= -github.com/creachadair/mds v0.13.4/go.mod h1:4vrFYUzTXMJpMBU+OA292I6IUxKWCCfZkgXg+/kBZMo= +github.com/creachadair/jrpc2 v1.1.2 h1:UOYMipEFYlwd5qmcvs9GZBurn3oXt1UDIX5JLjWWFzo= +github.com/creachadair/jrpc2 v1.1.2/go.mod h1:JcCe2Eny3lIvVwZLm92WXyU+tNUgTBWFCLMsfNkjEGk= +github.com/creachadair/mds v0.3.0 h1:uKbCKVtd3iOKVv3uviOm13fFNfe9qoCXJh1Vo7y3Kr0= +github.com/creachadair/mds v0.3.0/go.mod h1:4vrFYUzTXMJpMBU+OA292I6IUxKWCCfZkgXg+/kBZMo= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/djherbis/fscache v0.10.1 h1:hDv+RGyvD+UDKyRYuLoVNbuRTnf2SrA2K3VyR1br9lk= +github.com/djherbis/fscache v0.10.1/go.mod h1:yyPYtkNnnPXsW+81lAcQS6yab3G2CRfnPLotBvtbf0c= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= @@ -112,8 +116,12 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/fatih/structs v1.0.0 h1:BrX964Rv5uQ3wwS+KRUAJCBBw5PQmgJfJ6v4yly5QwU= github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= @@ -142,8 +150,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2 github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= @@ -222,8 +230,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -364,8 +372,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= -github.com/stellar/go v0.0.0-20240207003209-73de95c8eb55 h1:YBpAp7uPf/lzGxKPOGh1D05bX7uDVybA39BYoPXpRu4= -github.com/stellar/go v0.0.0-20240207003209-73de95c8eb55/go.mod h1:Ka4piwZT4Q9799f+BZeaKkAiYo4UpIWXyu0oSUbCVfM= +github.com/stellar/go v0.0.0-20240416162339-73233da7c30e h1:nqiU0AQQi+y8jyAPqG9Hk+JPPxOojcwLhcuK63Sq1pU= +github.com/stellar/go v0.0.0-20240416162339-73233da7c30e/go.mod h1:ckzsX0B0qfTMVZQJtPELJLs7cJ6xXMYHPVLyIsReGsU= github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2 h1:OzCVd0SV5qE3ZcDeSFCmOWLZfEWZ3Oe8KtmSOYKEVWE= github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2/go.mod h1:yoxyU/M8nl9LKeWIoBrbDPQ7Cy+4jxRcWcOayZ4BMps= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -418,14 +426,18 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= -go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= -go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= -go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= -go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= -go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= -go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= -go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= +go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= +go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= +go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= +go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= +go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -439,8 +451,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -518,8 +530,8 @@ golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -529,8 +541,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= -golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -599,8 +611,8 @@ golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -618,6 +630,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -673,8 +687,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -694,8 +708,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.149.0 h1:b2CqT6kG+zqJIVKRQ3ELJVLN1PwHZ6DJ3dW8yl82rgY= -google.golang.org/api v0.149.0/go.mod h1:Mwn1B7JTXrzXtnvmzQE2BD6bYZQ8DShKZDZbeN9I7qI= +google.golang.org/api v0.157.0 h1:ORAeqmbrrozeyw5NjnMxh7peHO0UzV4wWYSwZeCUb20= +google.golang.org/api v0.157.0/go.mod h1:+z4v4ufbZ1WEpld6yMGHyggs+PmAHiaLNj5ytP3N01g= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -741,12 +755,12 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos= -google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY= -google.golang.org/genproto/googleapis/api v0.0.0-20231211222908-989df2bf70f3 h1:EWIeHfGuUf00zrVZGEgYFxok7plSAXBGcH7NNdMAWvA= -google.golang.org/genproto/googleapis/api v0.0.0-20231211222908-989df2bf70f3/go.mod h1:k2dtGpRrbsSyKcNPKKI5sstZkrNCZwpU/ns96JoHbGg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= +google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg= +google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k= +google.golang.org/genproto/googleapis/api v0.0.0-20240122161410-6c6643bf1457 h1:KHBtwE+eQc3+NxpjmRFlQ3pJQ2FNnhhgB9xOV8kyBuU= +google.golang.org/genproto/googleapis/api v0.0.0-20240122161410-6c6643bf1457/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac h1:nUQEQmH/csSvFECKYRv6HWEyypysidKl2I6Qpsglq/0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -784,6 +798,10 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/djherbis/atime.v1 v1.0.0 h1:eMRqB/JrLKocla2PBPKgQYg/p5UG4L6AUAs92aP7F60= +gopkg.in/djherbis/atime.v1 v1.0.0/go.mod h1:hQIUStKmJfvf7xdh/wtK84qe+DsTV5LnA9lzxxtPpJ8= +gopkg.in/djherbis/stream.v1 v1.3.1 h1:uGfmsOY1qqMjQQphhRBSGLyA9qumJ56exkRu9ASTjCw= +gopkg.in/djherbis/stream.v1 v1.3.1/go.mod h1:aEV8CBVRmSpLamVJfM903Npic1IKmb2qS30VAZ+sssg= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/gavv/httpexpect.v1 v1.0.0-20170111145843-40724cf1e4a0 h1:r5ptJ1tBxVAeqw4CrYWhXIMr0SybY3CDHuIbCg5CFVw= gopkg.in/gavv/httpexpect.v1 v1.0.0-20170111145843-40724cf1e4a0/go.mod h1:WtiW9ZA1LdaWqtQRo1VbIL/v4XZ8NDta+O/kSpGgVek= From fce765b11206c5fc8bc66567a13b6d72727422d7 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Tue, 16 Apr 2024 15:38:33 -0400 Subject: [PATCH 16/57] Go mod changes - 2 --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index b383560c..1adf2c2d 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ toolchain go1.22.1 require ( github.com/Masterminds/squirrel v1.5.4 github.com/cenkalti/backoff/v4 v4.2.1 - github.com/creachadair/jrpc2 v1.1.2 + github.com/creachadair/jrpc2 v1.2.0 github.com/go-chi/chi v4.1.2+incompatible github.com/go-git/go-git/v5 v5.9.0 github.com/mattn/go-sqlite3 v1.14.17 @@ -81,7 +81,7 @@ require ( github.com/aws/aws-sdk-go v1.45.27 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/creachadair/mds v0.3.0 // indirect + github.com/creachadair/mds v0.13.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect diff --git a/go.sum b/go.sum index 2cd276e2..5d76787d 100644 --- a/go.sum +++ b/go.sum @@ -94,10 +94,10 @@ github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnht github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creachadair/jrpc2 v1.1.2 h1:UOYMipEFYlwd5qmcvs9GZBurn3oXt1UDIX5JLjWWFzo= -github.com/creachadair/jrpc2 v1.1.2/go.mod h1:JcCe2Eny3lIvVwZLm92WXyU+tNUgTBWFCLMsfNkjEGk= -github.com/creachadair/mds v0.3.0 h1:uKbCKVtd3iOKVv3uviOm13fFNfe9qoCXJh1Vo7y3Kr0= -github.com/creachadair/mds v0.3.0/go.mod h1:4vrFYUzTXMJpMBU+OA292I6IUxKWCCfZkgXg+/kBZMo= +github.com/creachadair/jrpc2 v1.2.0 h1:SXr0OgnwM0X18P+HccJP0uT3KGSDk/BCSRlJBvE2bMY= +github.com/creachadair/jrpc2 v1.2.0/go.mod h1:66uKSdr6tR5ZeNvkIjDSbbVUtOv0UhjS/vcd8ECP7Iw= +github.com/creachadair/mds v0.13.4 h1:RgU0MhiVqkzp6/xtNWhK6Pw7tDeaVuGFtA0UA2RBYvY= +github.com/creachadair/mds v0.13.4/go.mod h1:4vrFYUzTXMJpMBU+OA292I6IUxKWCCfZkgXg+/kBZMo= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= From 60055da83de5cf67e95dee15237b3f7c9e728cf8 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Wed, 17 Apr 2024 11:49:09 -0400 Subject: [PATCH 17/57] Add unittests - 1 --- cmd/soroban-rpc/internal/db/ledger.go | 16 - .../methods/get_latest_ledger_test.go | 4 - .../internal/methods/get_transactions.go | 54 ++-- .../internal/methods/get_transactions_test.go | 275 ++++++++++++++++++ cmd/soroban-rpc/internal/util/mocks.go | 133 +++++++++ 5 files changed, 436 insertions(+), 46 deletions(-) create mode 100644 cmd/soroban-rpc/internal/methods/get_transactions_test.go create mode 100644 cmd/soroban-rpc/internal/util/mocks.go diff --git a/cmd/soroban-rpc/internal/db/ledger.go b/cmd/soroban-rpc/internal/db/ledger.go index b67a4e66..1b4b0aa2 100644 --- a/cmd/soroban-rpc/internal/db/ledger.go +++ b/cmd/soroban-rpc/internal/db/ledger.go @@ -17,7 +17,6 @@ type StreamLedgerFn func(xdr.LedgerCloseMeta) error type LedgerReader interface { GetLedger(ctx context.Context, sequence uint32) (xdr.LedgerCloseMeta, bool, error) - //GetLedgers(ctx context.Context, startSequence uint32, endSequence uint32) ([]xdr.LedgerCloseMeta, error) StreamAllLedgers(ctx context.Context, f StreamLedgerFn) error } @@ -70,21 +69,6 @@ func (r ledgerReader) GetLedger(ctx context.Context, sequence uint32) (xdr.Ledge } } -//func (r ledgerReader) GetLedgers(ctx context.Context, startSequence uint32, endSequence uint32) ([]xdr.LedgerCloseMeta, error) { -// sql := sq.Select("meta"). -// From(ledgerCloseMetaTableName). -// Where( -// sq.And{ -// sq.GtOrEq{"sequence": startSequence}, -// sq.LtOrEq{"sequence": endSequence}, -// }) -// var results []xdr.LedgerCloseMeta -// if err := r.db.Select(ctx, &results, sql); err != nil { -// return []xdr.LedgerCloseMeta{}, err -// } -// return results, nil -//} - type ledgerWriter struct { stmtCache *sq.StmtCache } diff --git a/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go b/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go index 8b1c3fe5..30e05afa 100644 --- a/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go +++ b/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go @@ -58,10 +58,6 @@ func (ledgerReader *ConstantLedgerReader) StreamAllLedgers(ctx context.Context, return nil } -func (ledgerReader *ConstantLedgerReader) GetLedgers(ctx context.Context, startSequence uint32, endSequence uint32) ([]xdr.LedgerCloseMeta, error) { - return []xdr.LedgerCloseMeta{}, nil -} - func createLedger(ledgerSequence uint32, protocolVersion uint32, hash byte) xdr.LedgerCloseMeta { return xdr.LedgerCloseMeta{ V: 1, diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 5395d9e2..110cd120 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -147,29 +147,22 @@ LedgerLoop: } } - txInfo := TransactionInfo{ - FeeBump: tx.Envelope.IsFeeBump(), - ApplicationOrder: int32(tx.Index), - Successful: tx.Result.Result.Successful(), - LedgerSequence: uint(ledger.LedgerSequence()), - } - if txInfo.Result, err = tx.Result.Result.MarshalBinary(); err != nil { - return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, - Message: err.Error(), - } - } - if txInfo.Meta, err = tx.UnsafeMeta.MarshalBinary(); err != nil { + txResult, txMeta, txEnvelope, err := h.getTransactionDetails(tx) + if err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, Message: err.Error(), } } - if txInfo.Envelope, err = tx.Envelope.MarshalBinary(); err != nil { - return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, - Message: err.Error(), - } + + txInfo := TransactionInfo{ + Result: txResult, + Meta: txMeta, + Envelope: txEnvelope, + FeeBump: tx.Envelope.IsFeeBump(), + ApplicationOrder: int32(tx.Index), + Successful: tx.Result.Result.Successful(), + LedgerSequence: uint(ledger.LedgerSequence()), } txns = append(txns, txInfo) @@ -199,16 +192,25 @@ LedgerLoop: } -func (h *transactionsRPCHandler) getLatestLedgerDetails(ctx context.Context) (sequence int64, ledgerCloseTime int64, err error) { - tx, err := h.ledgerEntryReader.NewTx(ctx) +func (h *transactionsRPCHandler) getTransactionDetails(tx ingest.LedgerTransaction) ([]byte, []byte, []byte, error) { + txResult, err := tx.Result.Result.MarshalBinary() if err != nil { - return 0, 0, err + return nil, nil, nil, err + } + txMeta, err := tx.UnsafeMeta.MarshalBinary() + if err != nil { + return nil, nil, nil, err + } + txEnvelope, err := tx.Envelope.MarshalBinary() + if err != nil { + return nil, nil, nil, err } - defer func() { - _ = tx.Done() - }() - latestSequence, err := tx.GetLatestLedgerSequence() + return txResult, txMeta, txEnvelope, nil +} + +func (h *transactionsRPCHandler) getLatestLedgerDetails(ctx context.Context) (sequence int64, ledgerCloseTime int64, err error) { + latestSequence, err := h.ledgerEntryReader.GetLatestLedgerSequence(ctx) if err != nil { return 0, 0, err } @@ -221,7 +223,7 @@ func (h *transactionsRPCHandler) getLatestLedgerDetails(ctx context.Context) (se return 0, 0, err } - return int64(latestLedger.LedgerSequence()), int64(latestLedger.LedgerHeaderHistoryEntry().Header.ScpValue.CloseTime), nil + return int64(latestSequence), int64(latestLedger.LedgerHeaderHistoryEntry().Header.ScpValue.CloseTime), nil } func NewGetTransactionsHandler(logger *log.Entry, ledgerReader db.LedgerReader, ledgerEntryReader db.LedgerEntryReader, maxLimit, defaultLimit uint, networkPassphrase string) jrpc2.Handler { diff --git a/cmd/soroban-rpc/internal/methods/get_transactions_test.go b/cmd/soroban-rpc/internal/methods/get_transactions_test.go new file mode 100644 index 00000000..dd82d76a --- /dev/null +++ b/cmd/soroban-rpc/internal/methods/get_transactions_test.go @@ -0,0 +1,275 @@ +package methods + +import ( + "context" + "testing" + + "github.com/golang/mock/gomock" + "github.com/stellar/go/support/errors" + "github.com/stellar/go/xdr" + "github.com/stretchr/testify/assert" + + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/transactions" + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/util" +) + +const ( + NetworkPassphrase string = "passphrase" + LatestLedger int64 = 1136657 + LatestLedgerCloseTimestamp int64 = 28419025 +) + +// createTestLedger Create a ledger with 2 transactions +func createTestLedger(sequence uint32) xdr.LedgerCloseMeta { + meta := txMeta(sequence, true) + meta.V1.TxProcessing = append(meta.V1.TxProcessing, xdr.TransactionResultMeta{ + TxApplyProcessing: xdr.TransactionMeta{ + V: 3, + Operations: &[]xdr.OperationMeta{}, + V3: &xdr.TransactionMetaV3{}, + }, + Result: xdr.TransactionResultPair{ + TransactionHash: txHash(sequence), + Result: transactionResult(false), + }, + }) + return meta +} + +func getMockReaders(ctrl *gomock.Controller, ledgerFound bool, err error) (*util.MockLedgerEntryReader, *util.MockLedgerReader) { + mockLedgerReader := util.NewMockLedgerReader(ctrl) + mockLedgerReader.EXPECT(). + GetLedger(gomock.Any(), gomock.Any()). + DoAndReturn(func(ctx context.Context, sequence uint32) (xdr.LedgerCloseMeta, bool, error) { + var meta xdr.LedgerCloseMeta + if ledgerFound { + meta = createTestLedger(sequence) + } + return meta, ledgerFound, err + }).AnyTimes() + + mockLedgerEntryReader := util.NewMockLedgerEntryReader(ctrl) + mockLedgerEntryReader.EXPECT(). + GetLatestLedgerSequence(gomock.Any()). + Return(uint32(LatestLedger), nil).AnyTimes() + + return mockLedgerEntryReader, mockLedgerReader +} + +func TestGetTransactions_DefaultLimit(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, nil) + + handler := transactionsRPCHandler{ + ledgerReader: mockLedgerReader, + ledgerEntryReader: mockLedgerEntryReader, + maxLimit: 100, + defaultLimit: 10, + networkPassphrase: NetworkPassphrase, + } + + request := GetTransactionsRequest{ + StartLedger: 1, + EndLedger: 2, + } + + response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) + assert.NoError(t, err) + + // assert latest ledger details + assert.Equal(t, response.LatestLedger, LatestLedger) + assert.Equal(t, response.LatestLedgerCloseTimestamp, LatestLedgerCloseTimestamp) + + // assert pagination + assert.Equal(t, int(response.Pagination.Limit), 10) + cursor := transactions.NewCursor(102, 1, 0) + assert.Equal(t, response.Pagination.Cursor, &cursor) + + // assert transactions result + assert.Equal(t, len(response.Transactions), 4) +} + +func TestGetTransactions_CustomLimit(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, nil) + + handler := transactionsRPCHandler{ + ledgerReader: mockLedgerReader, + ledgerEntryReader: mockLedgerEntryReader, + maxLimit: 100, + defaultLimit: 10, + networkPassphrase: NetworkPassphrase, + } + + request := GetTransactionsRequest{ + StartLedger: 1, + EndLedger: 2, + Pagination: &TransactionsPaginationOptions{ + Limit: 2, + }, + } + + response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) + assert.NoError(t, err) + + // assert latest ledger details + assert.Equal(t, response.LatestLedger, LatestLedger) + assert.Equal(t, response.LatestLedgerCloseTimestamp, LatestLedgerCloseTimestamp) + + // assert pagination + assert.Equal(t, int(response.Pagination.Limit), 2) + cursor := transactions.NewCursor(101, 1, 0) + assert.Equal(t, response.Pagination.Cursor, &cursor) + + // assert transactions result + assert.Equal(t, len(response.Transactions), 2) + assert.Equal(t, int(response.Transactions[0].LedgerSequence), 101) + assert.Equal(t, int(response.Transactions[1].LedgerSequence), 101) + +} + +func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, nil) + + handler := transactionsRPCHandler{ + ledgerReader: mockLedgerReader, + ledgerEntryReader: mockLedgerEntryReader, + maxLimit: 100, + defaultLimit: 10, + networkPassphrase: NetworkPassphrase, + } + + request := GetTransactionsRequest{ + EndLedger: 2, + Pagination: &TransactionsPaginationOptions{ + Cursor: &transactions.Cursor{ + LedgerSequence: 1, + TxIdx: 0, + OpIdx: 0, + }, + Limit: 2, + }, + } + + response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) + assert.NoError(t, err) + + // assert latest ledger details + assert.Equal(t, response.LatestLedger, LatestLedger) + assert.Equal(t, response.LatestLedgerCloseTimestamp, LatestLedgerCloseTimestamp) + + // assert pagination + assert.Equal(t, int(response.Pagination.Limit), 2) + cursor := transactions.NewCursor(102, 0, 0) + assert.Equal(t, response.Pagination.Cursor, &cursor) + + // assert transactions result + assert.Equal(t, len(response.Transactions), 2) + assert.Equal(t, int(response.Transactions[0].LedgerSequence), 101) + assert.Equal(t, int(response.Transactions[1].LedgerSequence), 102) +} + +func TestGetTransactions_LedgerNotFound(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, false, nil) + + handler := transactionsRPCHandler{ + ledgerReader: mockLedgerReader, + ledgerEntryReader: mockLedgerEntryReader, + maxLimit: 100, + defaultLimit: 10, + networkPassphrase: NetworkPassphrase, + } + + request := GetTransactionsRequest{ + StartLedger: 1, + EndLedger: 2, + } + + response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) + assert.Equal(t, err.Error(), "[-32602] ledger close meta not found") + assert.Nil(t, response.Transactions) +} + +func TestGetTransactions_LedgerDbError(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + err := errors.New("error reading from db") + mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, false, err) + + handler := transactionsRPCHandler{ + ledgerReader: mockLedgerReader, + ledgerEntryReader: mockLedgerEntryReader, + maxLimit: 100, + defaultLimit: 10, + networkPassphrase: NetworkPassphrase, + } + + request := GetTransactionsRequest{ + StartLedger: 1, + EndLedger: 2, + } + + response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) + assert.Equal(t, err.Error(), "[-32602] error reading from db") + assert.Nil(t, response.Transactions) +} + +func TestGetTransactions_InvalidLedgerRange(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, nil) + + handler := transactionsRPCHandler{ + ledgerReader: mockLedgerReader, + ledgerEntryReader: mockLedgerEntryReader, + maxLimit: 100, + defaultLimit: 10, + networkPassphrase: NetworkPassphrase, + } + + request := GetTransactionsRequest{ + StartLedger: 3, + EndLedger: 2, + } + + _, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) + assert.Equal(t, err.Error(), "[-32602] end ledger cannot be less than start ledger") +} + +func TestGetTransactions_LimitGreaterThanMaxLimit(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, nil) + + handler := transactionsRPCHandler{ + ledgerReader: mockLedgerReader, + ledgerEntryReader: mockLedgerEntryReader, + maxLimit: 100, + defaultLimit: 10, + networkPassphrase: NetworkPassphrase, + } + + request := GetTransactionsRequest{ + StartLedger: 1, + EndLedger: 2, + Pagination: &TransactionsPaginationOptions{ + Limit: 200, + }, + } + + _, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) + assert.Equal(t, err.Error(), "[-32602] limit must not exceed 100") +} diff --git a/cmd/soroban-rpc/internal/util/mocks.go b/cmd/soroban-rpc/internal/util/mocks.go new file mode 100644 index 00000000..acfd2d51 --- /dev/null +++ b/cmd/soroban-rpc/internal/util/mocks.go @@ -0,0 +1,133 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/db (interfaces: LedgerReader,LedgerEntryReader) +package util + +import ( + context "context" + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + xdr "github.com/stellar/go/xdr" + db "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/db" +) + +// MockLedgerReader is a mock of LedgerReader interface. +type MockLedgerReader struct { + ctrl *gomock.Controller + recorder *MockLedgerReaderMockRecorder +} + +// MockLedgerReaderMockRecorder is the mock recorder for MockLedgerReader. +type MockLedgerReaderMockRecorder struct { + mock *MockLedgerReader +} + +// NewMockLedgerReader creates a new mock instance. +func NewMockLedgerReader(ctrl *gomock.Controller) *MockLedgerReader { + mock := &MockLedgerReader{ctrl: ctrl} + mock.recorder = &MockLedgerReaderMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockLedgerReader) EXPECT() *MockLedgerReaderMockRecorder { + return m.recorder +} + +// GetLedger mocks base method. +func (m *MockLedgerReader) GetLedger(arg0 context.Context, arg1 uint32) (xdr.LedgerCloseMeta, bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetLedger", arg0, arg1) + ret0, _ := ret[0].(xdr.LedgerCloseMeta) + ret1, _ := ret[1].(bool) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetLedger indicates an expected call of GetLedger. +func (mr *MockLedgerReaderMockRecorder) GetLedger(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLedger", reflect.TypeOf((*MockLedgerReader)(nil).GetLedger), arg0, arg1) +} + +// StreamAllLedgers mocks base method. +func (m *MockLedgerReader) StreamAllLedgers(arg0 context.Context, arg1 db.StreamLedgerFn) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StreamAllLedgers", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// StreamAllLedgers indicates an expected call of StreamAllLedgers. +func (mr *MockLedgerReaderMockRecorder) StreamAllLedgers(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StreamAllLedgers", reflect.TypeOf((*MockLedgerReader)(nil).StreamAllLedgers), arg0, arg1) +} + +// MockLedgerEntryReader is a mock of LedgerEntryReader interface. +type MockLedgerEntryReader struct { + ctrl *gomock.Controller + recorder *MockLedgerEntryReaderMockRecorder +} + +// MockLedgerEntryReaderMockRecorder is the mock recorder for MockLedgerEntryReader. +type MockLedgerEntryReaderMockRecorder struct { + mock *MockLedgerEntryReader +} + +// NewMockLedgerEntryReader creates a new mock instance. +func NewMockLedgerEntryReader(ctrl *gomock.Controller) *MockLedgerEntryReader { + mock := &MockLedgerEntryReader{ctrl: ctrl} + mock.recorder = &MockLedgerEntryReaderMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockLedgerEntryReader) EXPECT() *MockLedgerEntryReaderMockRecorder { + return m.recorder +} + +// GetLatestLedgerSequence mocks base method. +func (m *MockLedgerEntryReader) GetLatestLedgerSequence(arg0 context.Context) (uint32, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetLatestLedgerSequence", arg0) + ret0, _ := ret[0].(uint32) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetLatestLedgerSequence indicates an expected call of GetLatestLedgerSequence. +func (mr *MockLedgerEntryReaderMockRecorder) GetLatestLedgerSequence(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLatestLedgerSequence", reflect.TypeOf((*MockLedgerEntryReader)(nil).GetLatestLedgerSequence), arg0) +} + +// NewCachedTx mocks base method. +func (m *MockLedgerEntryReader) NewCachedTx(arg0 context.Context) (db.LedgerEntryReadTx, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewCachedTx", arg0) + ret0, _ := ret[0].(db.LedgerEntryReadTx) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// NewCachedTx indicates an expected call of NewCachedTx. +func (mr *MockLedgerEntryReaderMockRecorder) NewCachedTx(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewCachedTx", reflect.TypeOf((*MockLedgerEntryReader)(nil).NewCachedTx), arg0) +} + +// NewTx mocks base method. +func (m *MockLedgerEntryReader) NewTx(arg0 context.Context) (db.LedgerEntryReadTx, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewTx", arg0) + ret0, _ := ret[0].(db.LedgerEntryReadTx) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// NewTx indicates an expected call of NewTx. +func (mr *MockLedgerEntryReaderMockRecorder) NewTx(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewTx", reflect.TypeOf((*MockLedgerEntryReader)(nil).NewTx), arg0) +} From 90f6b5b28fd1f70acb0c7d7acda096d59d99c528 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Wed, 17 Apr 2024 11:53:03 -0400 Subject: [PATCH 18/57] Update go.mod and go.sum --- go.mod | 1 + go.sum | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/go.mod b/go.mod index 1adf2c2d..6f0e33e0 100644 --- a/go.mod +++ b/go.mod @@ -37,6 +37,7 @@ require ( github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/s2a-go v0.1.7 // indirect github.com/google/uuid v1.5.0 // indirect diff --git a/go.sum b/go.sum index 5d76787d..0cac2190 100644 --- a/go.sum +++ b/go.sum @@ -175,6 +175,8 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -417,6 +419,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= @@ -488,6 +491,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= @@ -524,6 +528,7 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= @@ -553,6 +558,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= @@ -591,8 +597,10 @@ golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -679,6 +687,7 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= From ba254f06b5b0758f170ff29e906ec97ea8e59ab1 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Thu, 18 Apr 2024 12:07:58 -0400 Subject: [PATCH 19/57] Add integration tests --- .../internal/methods/get_transactions.go | 2 +- .../internal/test/get_transactions_test.go | 128 ++++++++++++++++++ go.mod | 4 +- go.sum | 4 +- 4 files changed, 133 insertions(+), 5 deletions(-) create mode 100644 cmd/soroban-rpc/internal/test/get_transactions_test.go diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 110cd120..1d9c419b 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -223,7 +223,7 @@ func (h *transactionsRPCHandler) getLatestLedgerDetails(ctx context.Context) (se return 0, 0, err } - return int64(latestSequence), int64(latestLedger.LedgerHeaderHistoryEntry().Header.ScpValue.CloseTime), nil + return int64(latestSequence), latestLedger.LedgerCloseTime(), nil } func NewGetTransactionsHandler(logger *log.Entry, ledgerReader db.LedgerReader, ledgerEntryReader db.LedgerEntryReader, maxLimit, defaultLimit uint, networkPassphrase string) jrpc2.Handler { diff --git a/cmd/soroban-rpc/internal/test/get_transactions_test.go b/cmd/soroban-rpc/internal/test/get_transactions_test.go new file mode 100644 index 00000000..7fabc5bc --- /dev/null +++ b/cmd/soroban-rpc/internal/test/get_transactions_test.go @@ -0,0 +1,128 @@ +package test + +import ( + "context" + "testing" + "time" + + "github.com/creachadair/jrpc2" + "github.com/creachadair/jrpc2/jhttp" + "github.com/stellar/go/keypair" + "github.com/stellar/go/txnbuild" + "github.com/stretchr/testify/assert" + + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/methods" +) + +func buildTxParams(account txnbuild.SimpleAccount) txnbuild.TransactionParams { + params := txnbuild.TransactionParams{ + SourceAccount: &account, + IncrementSequenceNum: true, + Operations: []txnbuild.Operation{ + &txnbuild.SetOptions{HomeDomain: txnbuild.NewHomeDomain("soroban.com")}, + }, + BaseFee: txnbuild.MinBaseFee, + Preconditions: txnbuild.Preconditions{TimeBounds: txnbuild.NewInfiniteTimeout()}, + } + return params +} + +func sendTransaction(t *testing.T, client *jrpc2.Client, kp *keypair.Full, transaction *txnbuild.Transaction) (string, error) { + tx, err := transaction.Sign(StandaloneNetworkPassphrase, kp) + assert.NoError(t, err) + b64, err := tx.Base64() + assert.NoError(t, err) + + request := methods.SendTransactionRequest{Transaction: b64} + var result methods.SendTransactionResponse + + expectedHashHex, err := tx.HashHex(StandaloneNetworkPassphrase) + assert.NoError(t, err) + + return expectedHashHex, client.CallResult(context.Background(), "sendTransaction", request, &result) +} + +func sendTransactions(t *testing.T, client *jrpc2.Client) []uint32 { + kp := keypair.Root(StandaloneNetworkPassphrase) + address := kp.Address() + + var hashes []string + for i := 0; i <= 2; i++ { + account := txnbuild.NewSimpleAccount(address, int64(i)) + tx, err := txnbuild.NewTransaction(buildTxParams(account)) + assert.NoError(t, err) + + hash, err := sendTransaction(t, client, kp, tx) + assert.NoError(t, err) + hashes = append(hashes, hash) + time.Sleep(1 * time.Second) + } + + var ledgers []uint32 + for _, hash := range hashes { + response := getTransaction(t, client, hash) + assert.NotNil(t, response) + ledgers = append(ledgers, response.Ledger) + } + return ledgers +} + +func TestGetTransactions(t *testing.T) { + test := NewTest(t, nil) + ch := jhttp.NewChannel(test.sorobanRPCURL(), nil) + client := jrpc2.NewClient(ch, nil) + + ledgers := sendTransactions(t, client) + + // Get transactions across multiple ledgers + var result methods.GetTransactionsResponse + request := methods.GetTransactionsRequest{ + StartLedger: ledgers[0], + EndLedger: ledgers[2], + } + err := client.CallResult(context.Background(), "getTransactions", request, &result) + assert.NoError(t, err) + assert.Equal(t, len(result.Transactions), 3) + assert.Equal(t, uint32(result.Transactions[0].LedgerSequence), ledgers[0]) + assert.Equal(t, uint32(result.Transactions[1].LedgerSequence), ledgers[1]) + assert.Equal(t, uint32(result.Transactions[2].LedgerSequence), ledgers[2]) + + // Get transactions from single ledger + request = methods.GetTransactionsRequest{ + StartLedger: ledgers[0], + EndLedger: ledgers[0], + } + err = client.CallResult(context.Background(), "getTransactions", request, &result) + assert.NoError(t, err) + assert.Equal(t, len(result.Transactions), 1) + assert.Equal(t, uint32(result.Transactions[0].LedgerSequence), ledgers[0]) + + // Get transactions with limit + request = methods.GetTransactionsRequest{ + StartLedger: ledgers[0], + EndLedger: ledgers[2], + Pagination: &methods.TransactionsPaginationOptions{ + Limit: 1, + }, + } + err = client.CallResult(context.Background(), "getTransactions", request, &result) + assert.NoError(t, err) + assert.Equal(t, len(result.Transactions), 1) + assert.Equal(t, uint32(result.Transactions[0].LedgerSequence), ledgers[0]) + + // Get transactions using previous result's cursor + cursor := result.Pagination.Cursor + request = methods.GetTransactionsRequest{ + EndLedger: ledgers[2], + Pagination: &methods.TransactionsPaginationOptions{ + Cursor: cursor, + Limit: 5, + }, + } + err = client.CallResult(context.Background(), "getTransactions", request, &result) + assert.NoError(t, err) + assert.Equal(t, len(result.Transactions), 2) + assert.Equal(t, uint32(result.Transactions[0].LedgerSequence), ledgers[1]) + assert.Equal(t, uint32(result.Transactions[1].LedgerSequence), ledgers[2]) + +} diff --git a/go.mod b/go.mod index 6f0e33e0..7031b481 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/creachadair/jrpc2 v1.2.0 github.com/go-chi/chi v4.1.2+incompatible github.com/go-git/go-git/v5 v5.9.0 + github.com/golang/mock v1.6.0 github.com/mattn/go-sqlite3 v1.14.17 github.com/pelletier/go-toml v1.9.5 github.com/prometheus/client_golang v1.17.0 @@ -18,7 +19,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - github.com/stellar/go v0.0.0-20240416162339-73233da7c30e + github.com/stellar/go v0.0.0-20240417192451-c63ad05d3e3b github.com/stretchr/testify v1.8.4 golang.org/x/mod v0.13.0 ) @@ -37,7 +38,6 @@ require ( github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/s2a-go v0.1.7 // indirect github.com/google/uuid v1.5.0 // indirect diff --git a/go.sum b/go.sum index 0cac2190..7ffc2c84 100644 --- a/go.sum +++ b/go.sum @@ -374,8 +374,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= -github.com/stellar/go v0.0.0-20240416162339-73233da7c30e h1:nqiU0AQQi+y8jyAPqG9Hk+JPPxOojcwLhcuK63Sq1pU= -github.com/stellar/go v0.0.0-20240416162339-73233da7c30e/go.mod h1:ckzsX0B0qfTMVZQJtPELJLs7cJ6xXMYHPVLyIsReGsU= +github.com/stellar/go v0.0.0-20240417192451-c63ad05d3e3b h1:oKqqeJBLfSe5NkFjYb1vacvxbw0NQr+j14NYVWvUkiA= +github.com/stellar/go v0.0.0-20240417192451-c63ad05d3e3b/go.mod h1:ckzsX0B0qfTMVZQJtPELJLs7cJ6xXMYHPVLyIsReGsU= github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2 h1:OzCVd0SV5qE3ZcDeSFCmOWLZfEWZ3Oe8KtmSOYKEVWE= github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2/go.mod h1:yoxyU/M8nl9LKeWIoBrbDPQ7Cy+4jxRcWcOayZ4BMps= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From cb3eae90d1c2cf115f3aa8a00bf713e728ca6c17 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Thu, 18 Apr 2024 12:59:07 -0400 Subject: [PATCH 20/57] Update go.mod and go.sum --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7031b481..1166dff8 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - github.com/stellar/go v0.0.0-20240417192451-c63ad05d3e3b + github.com/stellar/go v0.0.0-20240418095127-12bbc681b7dd github.com/stretchr/testify v1.8.4 golang.org/x/mod v0.13.0 ) diff --git a/go.sum b/go.sum index 7ffc2c84..4d7d06f7 100644 --- a/go.sum +++ b/go.sum @@ -374,8 +374,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= -github.com/stellar/go v0.0.0-20240417192451-c63ad05d3e3b h1:oKqqeJBLfSe5NkFjYb1vacvxbw0NQr+j14NYVWvUkiA= -github.com/stellar/go v0.0.0-20240417192451-c63ad05d3e3b/go.mod h1:ckzsX0B0qfTMVZQJtPELJLs7cJ6xXMYHPVLyIsReGsU= +github.com/stellar/go v0.0.0-20240418095127-12bbc681b7dd h1:9yUSoNtvHX3Rc3VmDiXuJv3cZlVZF+L/sYWrrZsNHuU= +github.com/stellar/go v0.0.0-20240418095127-12bbc681b7dd/go.mod h1:ckzsX0B0qfTMVZQJtPELJLs7cJ6xXMYHPVLyIsReGsU= github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2 h1:OzCVd0SV5qE3ZcDeSFCmOWLZfEWZ3Oe8KtmSOYKEVWE= github.com/stellar/go-xdr v0.0.0-20231122183749-b53fb00bcac2/go.mod h1:yoxyU/M8nl9LKeWIoBrbDPQ7Cy+4jxRcWcOayZ4BMps= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From a75205c731b805dd81126203dec9000ec01cf885 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Thu, 18 Apr 2024 15:21:24 -0400 Subject: [PATCH 21/57] Add ledgerSeq to error string --- cmd/soroban-rpc/internal/methods/get_transactions.go | 4 ++-- cmd/soroban-rpc/internal/methods/get_transactions_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 1d9c419b..72ca57d6 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -106,7 +106,7 @@ LedgerLoop: ledger, found, err := h.ledgerReader.GetLedger(ctx, ledgerSeq) if (err != nil) || (!found) { if err == nil { - err = errors.New("ledger close meta not found") + err = errors.Errorf("ledger close meta not found: %d", ledgerSeq) } return GetTransactionsResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, @@ -218,7 +218,7 @@ func (h *transactionsRPCHandler) getLatestLedgerDetails(ctx context.Context) (se latestLedger, found, err := h.ledgerReader.GetLedger(ctx, latestSequence) if (err != nil) || (!found) { if err == nil { - err = errors.New("ledger close meta not found") + err = errors.Errorf("ledger close meta not found: %d", latestSequence) } return 0, 0, err } diff --git a/cmd/soroban-rpc/internal/methods/get_transactions_test.go b/cmd/soroban-rpc/internal/methods/get_transactions_test.go index dd82d76a..e12d5d1b 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions_test.go @@ -196,7 +196,7 @@ func TestGetTransactions_LedgerNotFound(t *testing.T) { } response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) - assert.Equal(t, err.Error(), "[-32602] ledger close meta not found") + assert.Equal(t, err.Error(), "[-32602] ledger close meta not found: 1") assert.Nil(t, response.Transactions) } From 65d2ab818d9645e1c71b6a9155a2031343c33470 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Thu, 18 Apr 2024 16:20:45 -0400 Subject: [PATCH 22/57] Add docstrings --- cmd/soroban-rpc/internal/methods/get_transactions.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 72ca57d6..f1c23afc 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -14,17 +14,21 @@ import ( "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/transactions" ) +// TransactionsPaginationOptions defines the available options for paginating through transactions. type TransactionsPaginationOptions struct { Cursor *transactions.Cursor `json:"cursor,omitempty"` Limit uint `json:"limit,omitempty"` } +// GetTransactionsRequest represents the request parameters for fetching transactions within a range of ledgers. type GetTransactionsRequest struct { StartLedger uint32 `json:"startLedger"` EndLedger uint32 `json:"endLedger"` Pagination *TransactionsPaginationOptions `json:"pagination,omitempty"` } +// isValid checks the validity of the request parameters. +// It returns an error if any parameter is out of the expected range or combination. func (req *GetTransactionsRequest) isValid(maxLimit uint) error { // Validate the start and end ledger sequence if req.StartLedger < 0 { @@ -47,6 +51,7 @@ func (req *GetTransactionsRequest) isValid(maxLimit uint) error { return nil } +// TransactionInfo represents the decoded transaction information from the ledger close meta. type TransactionInfo struct { Result []byte `json:"result"` Meta []byte `json:"meta"` @@ -57,6 +62,7 @@ type TransactionInfo struct { LedgerSequence uint `json:"ledgerSequence"` } +// GetTransactionsResponse encapsulates the response structure for getTransactions queries. type GetTransactionsResponse struct { Transactions []TransactionInfo `json:"transactions"` LatestLedger int64 `json:"latestLedger"` @@ -73,6 +79,8 @@ type transactionsRPCHandler struct { networkPassphrase string } +// getTransactionsByLedgerSequence fetches transactions between the start and end ledgers, inclusive of both. +// The number of ledgers returned are tuned using the pagination options - cursor and limit. func (h *transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Context, request GetTransactionsRequest) (GetTransactionsResponse, error) { err := request.isValid(h.maxLimit) if err != nil { @@ -192,6 +200,7 @@ LedgerLoop: } +// getTransactionDetails fetches XDR for the following transaction details - result, meta and envelope. func (h *transactionsRPCHandler) getTransactionDetails(tx ingest.LedgerTransaction) ([]byte, []byte, []byte, error) { txResult, err := tx.Result.Result.MarshalBinary() if err != nil { @@ -209,6 +218,7 @@ func (h *transactionsRPCHandler) getTransactionDetails(tx ingest.LedgerTransacti return txResult, txMeta, txEnvelope, nil } +// getLatestLedgerDetails fetches the latest ledger sequence and close time. func (h *transactionsRPCHandler) getLatestLedgerDetails(ctx context.Context) (sequence int64, ledgerCloseTime int64, err error) { latestSequence, err := h.ledgerEntryReader.GetLatestLedgerSequence(ctx) if err != nil { From dae0624990234fcff9087051a3ebe369cde1fd39 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Thu, 18 Apr 2024 16:22:03 -0400 Subject: [PATCH 23/57] Change transactions limits --- cmd/soroban-rpc/internal/config/options.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/soroban-rpc/internal/config/options.go b/cmd/soroban-rpc/internal/config/options.go index d9099dd4..3335c25f 100644 --- a/cmd/soroban-rpc/internal/config/options.go +++ b/cmd/soroban-rpc/internal/config/options.go @@ -251,13 +251,13 @@ func (cfg *Config) options() ConfigOptions { Name: "max-transactions-limit", Usage: "Maximum amount of transactions allowed in a single getTransactions response", ConfigKey: &cfg.MaxTransactionsLimit, - DefaultValue: uint(10000), + DefaultValue: uint(200), }, { Name: "default-transactions-limit", Usage: "Default cap on the amount of transactions included in a single getTransactions response", ConfigKey: &cfg.DefaultTransactionsLimit, - DefaultValue: uint(100), + DefaultValue: uint(50), Validate: func(co *ConfigOption) error { if cfg.DefaultTransactionsLimit > cfg.MaxTransactionsLimit { return fmt.Errorf( From f1a0a871c3cc1c0bf880ffba0034ade548eccfbe Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Thu, 18 Apr 2024 16:25:08 -0400 Subject: [PATCH 24/57] add defensive check for error other than EOF --- cmd/soroban-rpc/internal/methods/get_transactions.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index f1c23afc..198fdd89 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -3,6 +3,7 @@ package methods import ( "context" "fmt" + "io" "github.com/creachadair/jrpc2" "github.com/creachadair/jrpc2/handler" @@ -138,8 +139,13 @@ LedgerLoop: } err = reader.Seek(startTxIdx) if err != nil { - // Seek returns EOF so we can move onto next ledger - continue + if err == io.EOF { + continue + } + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } } // Decode transaction info from ledger meta From 364ee929030b5ca4daaf3908eb6c5dbecdab008b Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Thu, 18 Apr 2024 16:27:12 -0400 Subject: [PATCH 25/57] add defensive check for error other than EOF - 2 --- cmd/soroban-rpc/internal/methods/get_transactions.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 198fdd89..518a0bac 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -155,6 +155,10 @@ LedgerLoop: tx, err := reader.Read() if err != nil { + if err == io.EOF { + // No more transactions to read. Start from next ledger + break + } return GetTransactionsResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, Message: err.Error(), From aeb0a847548639392187924c1a93b1ea1b005edb Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Thu, 18 Apr 2024 16:31:15 -0400 Subject: [PATCH 26/57] Change ledger sequence to uint32 --- .../internal/methods/get_transactions.go | 4 ++-- .../internal/test/get_transactions_test.go | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 518a0bac..d3fbf819 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -60,7 +60,7 @@ type TransactionInfo struct { FeeBump bool `json:"feeBump"` ApplicationOrder int32 `json:"applicationOrder"` Successful bool `json:"successful"` - LedgerSequence uint `json:"ledgerSequence"` + LedgerSequence uint32 `json:"ledgerSequence"` } // GetTransactionsResponse encapsulates the response structure for getTransactions queries. @@ -180,7 +180,7 @@ LedgerLoop: FeeBump: tx.Envelope.IsFeeBump(), ApplicationOrder: int32(tx.Index), Successful: tx.Result.Result.Successful(), - LedgerSequence: uint(ledger.LedgerSequence()), + LedgerSequence: ledger.LedgerSequence(), } txns = append(txns, txInfo) diff --git a/cmd/soroban-rpc/internal/test/get_transactions_test.go b/cmd/soroban-rpc/internal/test/get_transactions_test.go index 7fabc5bc..0e7b3350 100644 --- a/cmd/soroban-rpc/internal/test/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/test/get_transactions_test.go @@ -83,9 +83,9 @@ func TestGetTransactions(t *testing.T) { err := client.CallResult(context.Background(), "getTransactions", request, &result) assert.NoError(t, err) assert.Equal(t, len(result.Transactions), 3) - assert.Equal(t, uint32(result.Transactions[0].LedgerSequence), ledgers[0]) - assert.Equal(t, uint32(result.Transactions[1].LedgerSequence), ledgers[1]) - assert.Equal(t, uint32(result.Transactions[2].LedgerSequence), ledgers[2]) + assert.Equal(t, result.Transactions[0].LedgerSequence, ledgers[0]) + assert.Equal(t, result.Transactions[1].LedgerSequence, ledgers[1]) + assert.Equal(t, result.Transactions[2].LedgerSequence, ledgers[2]) // Get transactions from single ledger request = methods.GetTransactionsRequest{ @@ -95,7 +95,7 @@ func TestGetTransactions(t *testing.T) { err = client.CallResult(context.Background(), "getTransactions", request, &result) assert.NoError(t, err) assert.Equal(t, len(result.Transactions), 1) - assert.Equal(t, uint32(result.Transactions[0].LedgerSequence), ledgers[0]) + assert.Equal(t, result.Transactions[0].LedgerSequence, ledgers[0]) // Get transactions with limit request = methods.GetTransactionsRequest{ @@ -108,7 +108,7 @@ func TestGetTransactions(t *testing.T) { err = client.CallResult(context.Background(), "getTransactions", request, &result) assert.NoError(t, err) assert.Equal(t, len(result.Transactions), 1) - assert.Equal(t, uint32(result.Transactions[0].LedgerSequence), ledgers[0]) + assert.Equal(t, result.Transactions[0].LedgerSequence, ledgers[0]) // Get transactions using previous result's cursor cursor := result.Pagination.Cursor @@ -122,7 +122,7 @@ func TestGetTransactions(t *testing.T) { err = client.CallResult(context.Background(), "getTransactions", request, &result) assert.NoError(t, err) assert.Equal(t, len(result.Transactions), 2) - assert.Equal(t, uint32(result.Transactions[0].LedgerSequence), ledgers[1]) - assert.Equal(t, uint32(result.Transactions[1].LedgerSequence), ledgers[2]) + assert.Equal(t, result.Transactions[0].LedgerSequence, ledgers[1]) + assert.Equal(t, result.Transactions[1].LedgerSequence, ledgers[2]) } From 2c5b2a465b9407bfa9d11da86c4c4687dec612ed Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Thu, 18 Apr 2024 17:16:24 -0400 Subject: [PATCH 27/57] Add comments/docstrings --- .../internal/methods/get_transactions.go | 2 +- .../internal/methods/get_transactions_test.go | 3 ++- .../internal/test/get_transactions_test.go | 22 +++++++++++++++++++ .../internal/transactions/cursor.go | 10 ++++----- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index d3fbf819..2520d7db 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -81,7 +81,7 @@ type transactionsRPCHandler struct { } // getTransactionsByLedgerSequence fetches transactions between the start and end ledgers, inclusive of both. -// The number of ledgers returned are tuned using the pagination options - cursor and limit. +// The number of ledgers returned can be tuned using the pagination options - cursor and limit. func (h *transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Context, request GetTransactionsRequest) (GetTransactionsResponse, error) { err := request.isValid(h.maxLimit) if err != nil { diff --git a/cmd/soroban-rpc/internal/methods/get_transactions_test.go b/cmd/soroban-rpc/internal/methods/get_transactions_test.go index e12d5d1b..10a1d042 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions_test.go @@ -19,7 +19,7 @@ const ( LatestLedgerCloseTimestamp int64 = 28419025 ) -// createTestLedger Create a ledger with 2 transactions +// createTestLedger Creates a test ledger with 2 transactions func createTestLedger(sequence uint32) xdr.LedgerCloseMeta { meta := txMeta(sequence, true) meta.V1.TxProcessing = append(meta.V1.TxProcessing, xdr.TransactionResultMeta{ @@ -36,6 +36,7 @@ func createTestLedger(sequence uint32) xdr.LedgerCloseMeta { return meta } +// getMockReaders build mock readers for interfaces - LedgerReader, LedgerEntryReader. func getMockReaders(ctrl *gomock.Controller, ledgerFound bool, err error) (*util.MockLedgerEntryReader, *util.MockLedgerReader) { mockLedgerReader := util.NewMockLedgerReader(ctrl) mockLedgerReader.EXPECT(). diff --git a/cmd/soroban-rpc/internal/test/get_transactions_test.go b/cmd/soroban-rpc/internal/test/get_transactions_test.go index 0e7b3350..325cda4b 100644 --- a/cmd/soroban-rpc/internal/test/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/test/get_transactions_test.go @@ -14,6 +14,11 @@ import ( "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/methods" ) +// buildTxParams constructs the parameters necessary for creating a transaction from the given account. +// +// account - the source account from which the transaction will originate. This account provides the starting sequence number. +// +// Returns a fully populated TransactionParams structure. func buildTxParams(account txnbuild.SimpleAccount) txnbuild.TransactionParams { params := txnbuild.TransactionParams{ SourceAccount: &account, @@ -27,6 +32,15 @@ func buildTxParams(account txnbuild.SimpleAccount) txnbuild.TransactionParams { return params } +// sendTransaction submits a single transaction to the Stellar network via the given JSON-RPC client and returns +// the transaction hash. +// +// t - the testing framework handle for assertions. +// client - the JSON-RPC client used to send the transaction. +// kp - the Stellar keypair used to sign the transaction. +// transaction - the Stellar transaction to be sent. +// +// Returns the expected transaction hash as a hex string and any error encountered during the transaction submission. func sendTransaction(t *testing.T, client *jrpc2.Client, kp *keypair.Full, transaction *txnbuild.Transaction) (string, error) { tx, err := transaction.Sign(StandaloneNetworkPassphrase, kp) assert.NoError(t, err) @@ -42,6 +56,14 @@ func sendTransaction(t *testing.T, client *jrpc2.Client, kp *keypair.Full, trans return expectedHashHex, client.CallResult(context.Background(), "sendTransaction", request, &result) } +// sendTransactions sends multiple transactions for testing purposes. +// It sends a total of three transactions, each from a new account sequence, and gathers the ledger +// numbers where these transactions were recorded. +// +// t - the testing framework handle for assertions. +// client - the JSON-RPC client used to send the transactions. +// +// Returns a slice of ledger numbers corresponding to where each transaction was recorded. func sendTransactions(t *testing.T, client *jrpc2.Client) []uint32 { kp := keypair.Root(StandaloneNetworkPassphrase) address := kp.Address() diff --git a/cmd/soroban-rpc/internal/transactions/cursor.go b/cmd/soroban-rpc/internal/transactions/cursor.go index adc9b53b..2ed87084 100644 --- a/cmd/soroban-rpc/internal/transactions/cursor.go +++ b/cmd/soroban-rpc/internal/transactions/cursor.go @@ -11,13 +11,13 @@ import ( ) type Cursor struct { - // LedgerSequence is the sequence of the ledger which emitted the event. + // LedgerSequence is the sequence of the ledger. LedgerSequence uint32 - // TxIdx is the index of the transaction within the ledger which emitted the event. + // TxIdx is the index of the transaction within. TxIdx uint32 - // Op is the index of the operation within the transaction which emitted the event. - // Note: Currently, there is no use for it (events are transaction-wide and not operation-specific) - // but we keep it in order to make the API future-proof. + // Op is the index of the operation within the transaction. + // Note: Currently, there is no use for it, + // but we keep it in order to make the API future-proof. OpIdx uint32 } From 95ce052227b9e62ea3b49002433228d08460456d Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Thu, 18 Apr 2024 17:35:41 -0400 Subject: [PATCH 28/57] Include only cursor in response --- .../internal/methods/get_transactions.go | 13 +++++-------- .../internal/methods/get_transactions_test.go | 9 +++------ .../internal/test/get_transactions_test.go | 3 +-- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 2520d7db..e7b9d5e4 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -65,10 +65,10 @@ type TransactionInfo struct { // GetTransactionsResponse encapsulates the response structure for getTransactions queries. type GetTransactionsResponse struct { - Transactions []TransactionInfo `json:"transactions"` - LatestLedger int64 `json:"latestLedger"` - LatestLedgerCloseTimestamp int64 `json:"latestLedgerCloseTimestamp"` - Pagination *TransactionsPaginationOptions `json:"pagination"` + Transactions []TransactionInfo `json:"transactions"` + LatestLedger int64 `json:"latestLedger"` + LatestLedgerCloseTimestamp int64 `json:"latestLedgerCloseTimestamp"` + Cursor *transactions.Cursor `json:"cursor"` } type transactionsRPCHandler struct { @@ -202,10 +202,7 @@ LedgerLoop: Transactions: txns, LatestLedger: latestLedgerSequence, LatestLedgerCloseTimestamp: latestLedgerCloseTime, - Pagination: &TransactionsPaginationOptions{ - Cursor: &cursor, - Limit: limit, - }, + Cursor: &cursor, }, nil } diff --git a/cmd/soroban-rpc/internal/methods/get_transactions_test.go b/cmd/soroban-rpc/internal/methods/get_transactions_test.go index 10a1d042..d75d2046 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions_test.go @@ -84,9 +84,8 @@ func TestGetTransactions_DefaultLimit(t *testing.T) { assert.Equal(t, response.LatestLedgerCloseTimestamp, LatestLedgerCloseTimestamp) // assert pagination - assert.Equal(t, int(response.Pagination.Limit), 10) cursor := transactions.NewCursor(102, 1, 0) - assert.Equal(t, response.Pagination.Cursor, &cursor) + assert.Equal(t, response.Cursor, &cursor) // assert transactions result assert.Equal(t, len(response.Transactions), 4) @@ -122,9 +121,8 @@ func TestGetTransactions_CustomLimit(t *testing.T) { assert.Equal(t, response.LatestLedgerCloseTimestamp, LatestLedgerCloseTimestamp) // assert pagination - assert.Equal(t, int(response.Pagination.Limit), 2) cursor := transactions.NewCursor(101, 1, 0) - assert.Equal(t, response.Pagination.Cursor, &cursor) + assert.Equal(t, response.Cursor, &cursor) // assert transactions result assert.Equal(t, len(response.Transactions), 2) @@ -167,9 +165,8 @@ func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { assert.Equal(t, response.LatestLedgerCloseTimestamp, LatestLedgerCloseTimestamp) // assert pagination - assert.Equal(t, int(response.Pagination.Limit), 2) cursor := transactions.NewCursor(102, 0, 0) - assert.Equal(t, response.Pagination.Cursor, &cursor) + assert.Equal(t, response.Cursor, &cursor) // assert transactions result assert.Equal(t, len(response.Transactions), 2) diff --git a/cmd/soroban-rpc/internal/test/get_transactions_test.go b/cmd/soroban-rpc/internal/test/get_transactions_test.go index 325cda4b..2ffd017a 100644 --- a/cmd/soroban-rpc/internal/test/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/test/get_transactions_test.go @@ -133,7 +133,7 @@ func TestGetTransactions(t *testing.T) { assert.Equal(t, result.Transactions[0].LedgerSequence, ledgers[0]) // Get transactions using previous result's cursor - cursor := result.Pagination.Cursor + cursor := result.Cursor request = methods.GetTransactionsRequest{ EndLedger: ledgers[2], Pagination: &methods.TransactionsPaginationOptions{ @@ -146,5 +146,4 @@ func TestGetTransactions(t *testing.T) { assert.Equal(t, len(result.Transactions), 2) assert.Equal(t, result.Transactions[0].LedgerSequence, ledgers[1]) assert.Equal(t, result.Transactions[1].LedgerSequence, ledgers[2]) - } From c27d20c06900626def5f5f98e1f0d3680783efb2 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Mon, 22 Apr 2024 16:02:35 -0400 Subject: [PATCH 29/57] Use toid instead of new cursor --- .../internal/daemon/interfaces/interfaces.go | 8 -- cmd/soroban-rpc/internal/events/cursor.go | 41 +++----- .../internal/methods/get_events.go | 8 +- .../internal/methods/get_events_test.go | 10 +- .../internal/methods/get_transactions.go | 32 +++--- .../internal/methods/get_transactions_test.go | 20 ++-- .../internal/transactions/cursor.go | 99 ------------------- 7 files changed, 50 insertions(+), 168 deletions(-) delete mode 100644 cmd/soroban-rpc/internal/transactions/cursor.go diff --git a/cmd/soroban-rpc/internal/daemon/interfaces/interfaces.go b/cmd/soroban-rpc/internal/daemon/interfaces/interfaces.go index 672fb492..529ecdef 100644 --- a/cmd/soroban-rpc/internal/daemon/interfaces/interfaces.go +++ b/cmd/soroban-rpc/internal/daemon/interfaces/interfaces.go @@ -20,11 +20,3 @@ type CoreClient interface { Info(ctx context.Context) (*proto.InfoResponse, error) SubmitTransaction(context.Context, string) (*proto.TXResponse, error) } - -type Cursor interface { - String() string - MarshalJSON() ([]byte, error) - UnmarshalJSON(b []byte) error - Cmp(other Cursor) int - ParseCursor(input string) (Cursor, error) -} diff --git a/cmd/soroban-rpc/internal/events/cursor.go b/cmd/soroban-rpc/internal/events/cursor.go index a1b6ba75..3fbfbecb 100644 --- a/cmd/soroban-rpc/internal/events/cursor.go +++ b/cmd/soroban-rpc/internal/events/cursor.go @@ -8,8 +8,6 @@ import ( "strings" "github.com/stellar/go/toid" - - "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/daemon/interfaces" ) // Cursor represents the position of a Soroban event. @@ -39,7 +37,7 @@ func (c Cursor) String() string { } // MarshalJSON marshals the cursor into JSON -func (c *Cursor) MarshalJSON() ([]byte, error) { +func (c Cursor) MarshalJSON() ([]byte, error) { return json.Marshal(c.String()) } @@ -50,40 +48,35 @@ func (c *Cursor) UnmarshalJSON(b []byte) error { return err } - parsed, err := c.ParseCursor(s) - if err != nil { + if parsed, err := ParseCursor(s); err != nil { return err - } - - if eventCursor, ok := parsed.(*Cursor); ok { - *c = *eventCursor } else { - return fmt.Errorf("parsed cursor could not be converted to Event cursor") + *c = parsed } return nil } // ParseCursor parses the given string and returns the corresponding cursor -func (c *Cursor) ParseCursor(input string) (interfaces.Cursor, error) { +func ParseCursor(input string) (Cursor, error) { parts := strings.SplitN(input, "-", 2) if len(parts) != 2 { - return &Cursor{}, fmt.Errorf("invalid event id %s", input) + return Cursor{}, fmt.Errorf("invalid event id %s", input) } // Parse the first part (toid) idInt, err := strconv.ParseInt(parts[0], 10, 64) //lint:ignore gomnd if err != nil { - return &Cursor{}, fmt.Errorf("invalid event id %s: %w", input, err) + return Cursor{}, fmt.Errorf("invalid event id %s: %w", input, err) } parsed := toid.Parse(idInt) // Parse the second part (event order) eventOrder, err := strconv.ParseUint(parts[1], 10, 32) //lint:ignore gomnd if err != nil { - return &Cursor{}, fmt.Errorf("invalid event id %s: %w", input, err) + return Cursor{}, fmt.Errorf("invalid event id %s: %w", input, err) } - return &Cursor{ + return Cursor{ Ledger: uint32(parsed.LedgerSequence), Tx: uint32(parsed.TransactionOrder), Op: uint32(parsed.OperationOrder), @@ -105,19 +98,17 @@ func cmp(a, b uint32) int { // 0 is returned if the c is equal to other. // 1 is returned if c is greater than other. // -1 is returned if c is less than other. -func (c Cursor) Cmp(other interfaces.Cursor) int { - otherCursor := other.(*Cursor) - - if c.Ledger == otherCursor.Ledger { - if c.Tx == otherCursor.Tx { - if c.Op == otherCursor.Op { - return cmp(c.Event, otherCursor.Event) +func (c Cursor) Cmp(other Cursor) int { + if c.Ledger == other.Ledger { + if c.Tx == other.Tx { + if c.Op == other.Op { + return cmp(c.Event, other.Event) } - return cmp(c.Op, otherCursor.Op) + return cmp(c.Op, other.Op) } - return cmp(c.Tx, otherCursor.Tx) + return cmp(c.Tx, other.Tx) } - return cmp(c.Ledger, otherCursor.Ledger) + return cmp(c.Ledger, other.Ledger) } var ( diff --git a/cmd/soroban-rpc/internal/methods/get_events.go b/cmd/soroban-rpc/internal/methods/get_events.go index 533603bd..8b4a9439 100644 --- a/cmd/soroban-rpc/internal/methods/get_events.go +++ b/cmd/soroban-rpc/internal/methods/get_events.go @@ -79,9 +79,9 @@ type EventInfo struct { } type GetEventsRequest struct { - StartLedger uint32 `json:"startLedger,omitempty"` - Filters []EventFilter `json:"filters"` - Pagination *EventsPaginationOptions `json:"pagination,omitempty"` + StartLedger uint32 `json:"startLedger,omitempty"` + Filters []EventFilter `json:"filters"` + Pagination *PaginationOptions `json:"pagination,omitempty"` } func (g *GetEventsRequest) Valid(maxLimit uint) error { @@ -288,7 +288,7 @@ func (s *SegmentFilter) UnmarshalJSON(p []byte) error { return nil } -type EventsPaginationOptions struct { +type PaginationOptions struct { Cursor *events.Cursor `json:"cursor,omitempty"` Limit uint `json:"limit,omitempty"` } diff --git a/cmd/soroban-rpc/internal/methods/get_events_test.go b/cmd/soroban-rpc/internal/methods/get_events_test.go index 7d86aedc..087a3ffd 100644 --- a/cmd/soroban-rpc/internal/methods/get_events_test.go +++ b/cmd/soroban-rpc/internal/methods/get_events_test.go @@ -410,7 +410,7 @@ func TestGetEventsRequestValid(t *testing.T) { assert.EqualError(t, (&GetEventsRequest{ StartLedger: 1, Filters: []EventFilter{}, - Pagination: &EventsPaginationOptions{Cursor: &events.Cursor{}}, + Pagination: &PaginationOptions{Cursor: &events.Cursor{}}, }).Valid(1000), "startLedger and cursor cannot both be set") assert.NoError(t, (&GetEventsRequest{ @@ -422,7 +422,7 @@ func TestGetEventsRequestValid(t *testing.T) { assert.EqualError(t, (&GetEventsRequest{ StartLedger: 1, Filters: []EventFilter{}, - Pagination: &EventsPaginationOptions{Limit: 1001}, + Pagination: &PaginationOptions{Limit: 1001}, }).Valid(1000), "limit must not exceed 1000") assert.EqualError(t, (&GetEventsRequest{ @@ -932,7 +932,7 @@ func TestGetEvents(t *testing.T) { results, err := handler.getEvents(GetEventsRequest{ StartLedger: 1, Filters: []EventFilter{}, - Pagination: &EventsPaginationOptions{Limit: 10}, + Pagination: &PaginationOptions{Limit: 10}, }) assert.NoError(t, err) @@ -1016,7 +1016,7 @@ func TestGetEvents(t *testing.T) { defaultLimit: 100, } results, err := handler.getEvents(GetEventsRequest{ - Pagination: &EventsPaginationOptions{ + Pagination: &PaginationOptions{ Cursor: id, Limit: 2, }, @@ -1048,7 +1048,7 @@ func TestGetEvents(t *testing.T) { assert.Equal(t, GetEventsResponse{expected, 5}, results) results, err = handler.getEvents(GetEventsRequest{ - Pagination: &EventsPaginationOptions{ + Pagination: &PaginationOptions{ Cursor: &events.Cursor{Ledger: 5, Tx: 2, Op: 0, Event: 1}, Limit: 2, }, diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index e7b9d5e4..5e9d1993 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -10,15 +10,15 @@ import ( "github.com/stellar/go/ingest" "github.com/stellar/go/support/errors" "github.com/stellar/go/support/log" + "github.com/stellar/go/toid" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/db" - "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/transactions" ) // TransactionsPaginationOptions defines the available options for paginating through transactions. type TransactionsPaginationOptions struct { - Cursor *transactions.Cursor `json:"cursor,omitempty"` - Limit uint `json:"limit,omitempty"` + Cursor *toid.ID `json:"cursor,omitempty"` + Limit uint `json:"limit,omitempty"` } // GetTransactionsRequest represents the request parameters for fetching transactions within a range of ledgers. @@ -65,10 +65,10 @@ type TransactionInfo struct { // GetTransactionsResponse encapsulates the response structure for getTransactions queries. type GetTransactionsResponse struct { - Transactions []TransactionInfo `json:"transactions"` - LatestLedger int64 `json:"latestLedger"` - LatestLedgerCloseTimestamp int64 `json:"latestLedgerCloseTimestamp"` - Cursor *transactions.Cursor `json:"cursor"` + Transactions []TransactionInfo `json:"transactions"` + LatestLedger int64 `json:"latestLedger"` + LatestLedgerCloseTimestamp int64 `json:"latestLedgerCloseTimestamp"` + Cursor *toid.ID `json:"cursor"` } type transactionsRPCHandler struct { @@ -92,14 +92,14 @@ func (h *transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Con } // Move start to pagination cursor - start := transactions.NewCursor(request.StartLedger, 0, 0) + start := toid.New(int32(request.StartLedger), 0, 0) limit := h.defaultLimit if request.Pagination != nil { if request.Pagination.Cursor != nil { - start = *request.Pagination.Cursor + start = request.Pagination.Cursor // increment tx index because, when paginating, // we start with the item right after the cursor - start.TxIdx++ + start.TransactionOrder++ } if request.Pagination.Limit > 0 { limit = request.Pagination.Limit @@ -108,11 +108,11 @@ func (h *transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Con // Iterate through each ledger and its transactions until limit or end range is reached var txns []TransactionInfo - var cursor transactions.Cursor + var cursor *toid.ID LedgerLoop: - for ledgerSeq := start.LedgerSequence; ledgerSeq <= request.EndLedger; ledgerSeq++ { + for ledgerSeq := start.LedgerSequence; ledgerSeq <= int32(request.EndLedger); ledgerSeq++ { // Get ledger close meta from db - ledger, found, err := h.ledgerReader.GetLedger(ctx, ledgerSeq) + ledger, found, err := h.ledgerReader.GetLedger(ctx, uint32(ledgerSeq)) if (err != nil) || (!found) { if err == nil { err = errors.Errorf("ledger close meta not found: %d", ledgerSeq) @@ -135,7 +135,7 @@ LedgerLoop: // Move the reader to specific tx idx startTxIdx := 0 if ledgerSeq == start.LedgerSequence { - startTxIdx = int(start.TxIdx) + startTxIdx = int(start.TransactionOrder) } err = reader.Seek(startTxIdx) if err != nil { @@ -151,7 +151,7 @@ LedgerLoop: // Decode transaction info from ledger meta txCount := ledger.CountTransactions() for i := startTxIdx; i < txCount; i++ { - cursor = transactions.NewCursor(ledger.LedgerSequence(), uint32(i), 0) + cursor = toid.New(int32(ledger.LedgerSequence()), int32(uint32(i)), 0) tx, err := reader.Read() if err != nil { @@ -202,7 +202,7 @@ LedgerLoop: Transactions: txns, LatestLedger: latestLedgerSequence, LatestLedgerCloseTimestamp: latestLedgerCloseTime, - Cursor: &cursor, + Cursor: cursor, }, nil } diff --git a/cmd/soroban-rpc/internal/methods/get_transactions_test.go b/cmd/soroban-rpc/internal/methods/get_transactions_test.go index d75d2046..9bf41707 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions_test.go @@ -6,10 +6,10 @@ import ( "github.com/golang/mock/gomock" "github.com/stellar/go/support/errors" + "github.com/stellar/go/toid" "github.com/stellar/go/xdr" "github.com/stretchr/testify/assert" - "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/transactions" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/util" ) @@ -84,8 +84,7 @@ func TestGetTransactions_DefaultLimit(t *testing.T) { assert.Equal(t, response.LatestLedgerCloseTimestamp, LatestLedgerCloseTimestamp) // assert pagination - cursor := transactions.NewCursor(102, 1, 0) - assert.Equal(t, response.Cursor, &cursor) + assert.Equal(t, response.Cursor, toid.New(102, 1, 0)) // assert transactions result assert.Equal(t, len(response.Transactions), 4) @@ -121,8 +120,7 @@ func TestGetTransactions_CustomLimit(t *testing.T) { assert.Equal(t, response.LatestLedgerCloseTimestamp, LatestLedgerCloseTimestamp) // assert pagination - cursor := transactions.NewCursor(101, 1, 0) - assert.Equal(t, response.Cursor, &cursor) + assert.Equal(t, response.Cursor, toid.New(101, 1, 0)) // assert transactions result assert.Equal(t, len(response.Transactions), 2) @@ -148,10 +146,10 @@ func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { request := GetTransactionsRequest{ EndLedger: 2, Pagination: &TransactionsPaginationOptions{ - Cursor: &transactions.Cursor{ - LedgerSequence: 1, - TxIdx: 0, - OpIdx: 0, + Cursor: &toid.ID{ + LedgerSequence: 1, + TransactionOrder: 0, + OperationOrder: 0, }, Limit: 2, }, @@ -165,8 +163,8 @@ func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { assert.Equal(t, response.LatestLedgerCloseTimestamp, LatestLedgerCloseTimestamp) // assert pagination - cursor := transactions.NewCursor(102, 0, 0) - assert.Equal(t, response.Cursor, &cursor) + cursor := toid.New(102, 0, 0) + assert.Equal(t, response.Cursor, cursor) // assert transactions result assert.Equal(t, len(response.Transactions), 2) diff --git a/cmd/soroban-rpc/internal/transactions/cursor.go b/cmd/soroban-rpc/internal/transactions/cursor.go deleted file mode 100644 index 2ed87084..00000000 --- a/cmd/soroban-rpc/internal/transactions/cursor.go +++ /dev/null @@ -1,99 +0,0 @@ -package transactions - -import ( - "encoding/json" - "fmt" - "strconv" - - "github.com/stellar/go/toid" - - "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/daemon/interfaces" -) - -type Cursor struct { - // LedgerSequence is the sequence of the ledger. - LedgerSequence uint32 - // TxIdx is the index of the transaction within. - TxIdx uint32 - // Op is the index of the operation within the transaction. - // Note: Currently, there is no use for it, - // but we keep it in order to make the API future-proof. - OpIdx uint32 -} - -// String returns a string representation of this cursor -func (c *Cursor) String() string { - return fmt.Sprintf( - "%019d", - toid.New(int32(c.LedgerSequence), int32(c.TxIdx), int32(c.OpIdx)).ToInt64(), - ) -} - -// MarshalJSON marshals the cursor into JSON -func (c *Cursor) MarshalJSON() ([]byte, error) { - return json.Marshal(c.String()) -} - -// UnmarshalJSON unmarshalls a cursor from the given JSON -func (c *Cursor) UnmarshalJSON(b []byte) error { - var s string - if err := json.Unmarshal(b, &s); err != nil { - return err - } - - parsed, err := c.ParseCursor(s) - if err != nil { - return err - } - - if txCursor, ok := parsed.(*Cursor); ok { - *c = *txCursor - } else { - return fmt.Errorf("parsed cursor could not be converted to Transaction cursor") - } - return nil -} - -// Cmp compares two cursors. -// 0 is returned if the c is equal to other. -// 1 is returned if c is greater than other. -// -1 is returned if c is less than other. -func (c *Cursor) Cmp(other interfaces.Cursor) int { - otherCursor := other.(*Cursor) - - if c.LedgerSequence == otherCursor.LedgerSequence { - return cmp(c.TxIdx, otherCursor.TxIdx) - } - return cmp(c.LedgerSequence, otherCursor.LedgerSequence) -} - -func (c *Cursor) ParseCursor(input string) (interfaces.Cursor, error) { - idInt, err := strconv.ParseInt(input, 10, 64) //lint:ignore gomnd - if err != nil { - return &Cursor{}, fmt.Errorf("invalid cursor %s: %w", input, err) - } - parsed := toid.Parse(idInt) - return &Cursor{ - LedgerSequence: uint32(parsed.LedgerSequence), - TxIdx: uint32(parsed.TransactionOrder), - OpIdx: uint32(parsed.OperationOrder), - }, nil -} - -func cmp(a, b uint32) int { - if a < b { - return -1 - } - if a > b { - return 1 - } - return 0 -} - -func NewCursor(sequence uint32, txIdx uint32, opIdx uint32) Cursor { - return Cursor{ - LedgerSequence: sequence, - TxIdx: txIdx, - OpIdx: opIdx, - } -} From 6837f79116149c96ae8cbb9af2cefbe81dc33822 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Mon, 22 Apr 2024 16:03:55 -0400 Subject: [PATCH 30/57] Revert cursor changes --- cmd/soroban-rpc/internal/events/cursor_test.go | 8 ++++---- cmd/soroban-rpc/internal/events/events.go | 13 ++++++------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/cmd/soroban-rpc/internal/events/cursor_test.go b/cmd/soroban-rpc/internal/events/cursor_test.go index 1c16f64b..6dfe1e58 100644 --- a/cmd/soroban-rpc/internal/events/cursor_test.go +++ b/cmd/soroban-rpc/internal/events/cursor_test.go @@ -9,7 +9,7 @@ import ( ) func TestParseCursor(t *testing.T) { - for _, cursor := range []*Cursor{ + for _, cursor := range []Cursor{ { Ledger: math.MaxInt32, Tx: 1048575, @@ -29,7 +29,7 @@ func TestParseCursor(t *testing.T) { Event: 1, }, } { - parsed, err := cursor.ParseCursor(cursor.String()) + parsed, err := ParseCursor(cursor.String()) assert.NoError(t, err) assert.Equal(t, cursor, parsed) } @@ -97,12 +97,12 @@ func TestCursorCmp(t *testing.T) { b := testCase.b expected := testCase.expected - if got := a.Cmp(&b); got != expected { + if got := a.Cmp(b); got != expected { t.Fatalf("expected (%v).Cmp(%v) to be %v but got %v", a, b, expected, got) } a, b = b, a expected *= -1 - if got := a.Cmp(&b); got != expected { + if got := a.Cmp(b); got != expected { t.Fatalf("expected (%v).Cmp(%v) to be %v but got %v", a, b, expected, got) } } diff --git a/cmd/soroban-rpc/internal/events/events.go b/cmd/soroban-rpc/internal/events/events.go index 3b570602..12e8e765 100644 --- a/cmd/soroban-rpc/internal/events/events.go +++ b/cmd/soroban-rpc/internal/events/events.go @@ -128,7 +128,7 @@ func (m *MemoryStore) Scan(eventRange Range, f ScanFunction) (lastLedgerInWindow timestamp := bucket.LedgerCloseTimestamp for _, event := range events { cur := event.cursor(bucket.LedgerSeq) - if eventRange.End.Cmp(&cur) <= 0 { + if eventRange.End.Cmp(cur) <= 0 { return } var diagnosticEvent xdr.DiagnosticEvent @@ -153,7 +153,7 @@ func (m *MemoryStore) validateRange(eventRange *Range) error { } firstBucket := m.eventsByLedger.Get(0) min := Cursor{Ledger: firstBucket.LedgerSeq} - if eventRange.Start.Cmp(&min) < 0 { + if eventRange.Start.Cmp(min) < 0 { if eventRange.ClampStart { eventRange.Start = min } else { @@ -161,10 +161,10 @@ func (m *MemoryStore) validateRange(eventRange *Range) error { } } max := Cursor{Ledger: min.Ledger + m.eventsByLedger.Len()} - if eventRange.Start.Cmp(&max) >= 0 { + if eventRange.Start.Cmp(max) >= 0 { return errors.New("start is after newest ledger") } - if eventRange.End.Cmp(&max) > 0 { + if eventRange.End.Cmp(max) > 0 { if eventRange.ClampEnd { eventRange.End = max } else { @@ -172,7 +172,7 @@ func (m *MemoryStore) validateRange(eventRange *Range) error { } } - if eventRange.Start.Cmp(&eventRange.End) >= 0 { + if eventRange.Start.Cmp(eventRange.End) >= 0 { return errors.New("start is not before end") } @@ -184,8 +184,7 @@ func (m *MemoryStore) validateRange(eventRange *Range) error { // events must be sorted in ascending order. func seek(events []event, cursor Cursor) []event { j := sort.Search(len(events), func(i int) bool { - cur := events[i].cursor(cursor.Ledger) - return cursor.Cmp(&cur) <= 0 + return cursor.Cmp(events[i].cursor(cursor.Ledger)) <= 0 }) return events[j:] } From 0f098fbe270f66130553914c682b40db6352e492 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Mon, 29 Apr 2024 10:20:47 -0400 Subject: [PATCH 31/57] Return cursor as string in result --- cmd/soroban-rpc/internal/methods/get_transactions.go | 12 ++++++------ .../internal/methods/get_transactions_test.go | 7 +++---- .../internal/test/get_transactions_test.go | 5 +++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 5e9d1993..41b5a3a9 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -68,7 +68,7 @@ type GetTransactionsResponse struct { Transactions []TransactionInfo `json:"transactions"` LatestLedger int64 `json:"latestLedger"` LatestLedgerCloseTimestamp int64 `json:"latestLedgerCloseTimestamp"` - Cursor *toid.ID `json:"cursor"` + Cursor string `json:"cursor"` } type transactionsRPCHandler struct { @@ -82,7 +82,7 @@ type transactionsRPCHandler struct { // getTransactionsByLedgerSequence fetches transactions between the start and end ledgers, inclusive of both. // The number of ledgers returned can be tuned using the pagination options - cursor and limit. -func (h *transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Context, request GetTransactionsRequest) (GetTransactionsResponse, error) { +func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Context, request GetTransactionsRequest) (GetTransactionsResponse, error) { err := request.isValid(h.maxLimit) if err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ @@ -151,7 +151,7 @@ LedgerLoop: // Decode transaction info from ledger meta txCount := ledger.CountTransactions() for i := startTxIdx; i < txCount; i++ { - cursor = toid.New(int32(ledger.LedgerSequence()), int32(uint32(i)), 0) + cursor = toid.New(int32(ledger.LedgerSequence()), int32(i), 0) tx, err := reader.Read() if err != nil { @@ -202,13 +202,13 @@ LedgerLoop: Transactions: txns, LatestLedger: latestLedgerSequence, LatestLedgerCloseTimestamp: latestLedgerCloseTime, - Cursor: cursor, + Cursor: cursor.String(), }, nil } // getTransactionDetails fetches XDR for the following transaction details - result, meta and envelope. -func (h *transactionsRPCHandler) getTransactionDetails(tx ingest.LedgerTransaction) ([]byte, []byte, []byte, error) { +func (h transactionsRPCHandler) getTransactionDetails(tx ingest.LedgerTransaction) ([]byte, []byte, []byte, error) { txResult, err := tx.Result.Result.MarshalBinary() if err != nil { return nil, nil, nil, err @@ -226,7 +226,7 @@ func (h *transactionsRPCHandler) getTransactionDetails(tx ingest.LedgerTransacti } // getLatestLedgerDetails fetches the latest ledger sequence and close time. -func (h *transactionsRPCHandler) getLatestLedgerDetails(ctx context.Context) (sequence int64, ledgerCloseTime int64, err error) { +func (h transactionsRPCHandler) getLatestLedgerDetails(ctx context.Context) (sequence int64, ledgerCloseTime int64, err error) { latestSequence, err := h.ledgerEntryReader.GetLatestLedgerSequence(ctx) if err != nil { return 0, 0, err diff --git a/cmd/soroban-rpc/internal/methods/get_transactions_test.go b/cmd/soroban-rpc/internal/methods/get_transactions_test.go index 9bf41707..8eafa16c 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions_test.go @@ -84,7 +84,7 @@ func TestGetTransactions_DefaultLimit(t *testing.T) { assert.Equal(t, response.LatestLedgerCloseTimestamp, LatestLedgerCloseTimestamp) // assert pagination - assert.Equal(t, response.Cursor, toid.New(102, 1, 0)) + assert.Equal(t, response.Cursor, toid.New(102, 1, 0).String()) // assert transactions result assert.Equal(t, len(response.Transactions), 4) @@ -120,7 +120,7 @@ func TestGetTransactions_CustomLimit(t *testing.T) { assert.Equal(t, response.LatestLedgerCloseTimestamp, LatestLedgerCloseTimestamp) // assert pagination - assert.Equal(t, response.Cursor, toid.New(101, 1, 0)) + assert.Equal(t, response.Cursor, toid.New(101, 1, 0).String()) // assert transactions result assert.Equal(t, len(response.Transactions), 2) @@ -163,8 +163,7 @@ func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { assert.Equal(t, response.LatestLedgerCloseTimestamp, LatestLedgerCloseTimestamp) // assert pagination - cursor := toid.New(102, 0, 0) - assert.Equal(t, response.Cursor, cursor) + assert.Equal(t, response.Cursor, toid.New(102, 0, 0).String()) // assert transactions result assert.Equal(t, len(response.Transactions), 2) diff --git a/cmd/soroban-rpc/internal/test/get_transactions_test.go b/cmd/soroban-rpc/internal/test/get_transactions_test.go index 2ffd017a..71adf1ec 100644 --- a/cmd/soroban-rpc/internal/test/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/test/get_transactions_test.go @@ -8,6 +8,7 @@ import ( "github.com/creachadair/jrpc2" "github.com/creachadair/jrpc2/jhttp" "github.com/stellar/go/keypair" + "github.com/stellar/go/toid" "github.com/stellar/go/txnbuild" "github.com/stretchr/testify/assert" @@ -133,11 +134,11 @@ func TestGetTransactions(t *testing.T) { assert.Equal(t, result.Transactions[0].LedgerSequence, ledgers[0]) // Get transactions using previous result's cursor - cursor := result.Cursor + cursor := toid.Parse(55834574848) request = methods.GetTransactionsRequest{ EndLedger: ledgers[2], Pagination: &methods.TransactionsPaginationOptions{ - Cursor: cursor, + Cursor: &cursor, Limit: 5, }, } From c9ddee4288fd35083fa06019e5a947a4dca9b859 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Mon, 29 Apr 2024 11:23:10 -0400 Subject: [PATCH 32/57] Refactor reader.Seek error handling --- .../internal/methods/get_transactions.go | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 41b5a3a9..191941d1 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -136,15 +136,11 @@ LedgerLoop: startTxIdx := 0 if ledgerSeq == start.LedgerSequence { startTxIdx = int(start.TransactionOrder) - } - err = reader.Seek(startTxIdx) - if err != nil { - if err == io.EOF { - continue - } - return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, - Message: err.Error(), + if ierr := reader.Seek(startTxIdx); ierr != nil && ierr != io.EOF { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } } } From 1c44f63b9ea9174ee567c5c9e72cba2b3ccbbda9 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Tue, 30 Apr 2024 09:39:16 -0400 Subject: [PATCH 33/57] Small refactoring --- cmd/soroban-rpc/internal/methods/get_transactions.go | 12 ++++++------ .../internal/test/get_transactions_test.go | 6 +++++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 191941d1..d1aad9cc 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -30,7 +30,7 @@ type GetTransactionsRequest struct { // isValid checks the validity of the request parameters. // It returns an error if any parameter is out of the expected range or combination. -func (req *GetTransactionsRequest) isValid(maxLimit uint) error { +func (req GetTransactionsRequest) isValid(maxLimit uint) error { // Validate the start and end ledger sequence if req.StartLedger < 0 { return errors.New("start ledger cannot be negative") @@ -52,8 +52,8 @@ func (req *GetTransactionsRequest) isValid(maxLimit uint) error { return nil } -// TransactionInfo represents the decoded transaction information from the ledger close meta. -type TransactionInfo struct { +// transactionInfo represents the decoded transaction information from the ledger close meta. +type transactionInfo struct { Result []byte `json:"result"` Meta []byte `json:"meta"` Envelope []byte `json:"envelope"` @@ -65,7 +65,7 @@ type TransactionInfo struct { // GetTransactionsResponse encapsulates the response structure for getTransactions queries. type GetTransactionsResponse struct { - Transactions []TransactionInfo `json:"transactions"` + Transactions []transactionInfo `json:"transactions"` LatestLedger int64 `json:"latestLedger"` LatestLedgerCloseTimestamp int64 `json:"latestLedgerCloseTimestamp"` Cursor string `json:"cursor"` @@ -107,7 +107,7 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont } // Iterate through each ledger and its transactions until limit or end range is reached - var txns []TransactionInfo + var txns []transactionInfo var cursor *toid.ID LedgerLoop: for ledgerSeq := start.LedgerSequence; ledgerSeq <= int32(request.EndLedger); ledgerSeq++ { @@ -169,7 +169,7 @@ LedgerLoop: } } - txInfo := TransactionInfo{ + txInfo := transactionInfo{ Result: txResult, Meta: txMeta, Envelope: txEnvelope, diff --git a/cmd/soroban-rpc/internal/test/get_transactions_test.go b/cmd/soroban-rpc/internal/test/get_transactions_test.go index 71adf1ec..f89a6e51 100644 --- a/cmd/soroban-rpc/internal/test/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/test/get_transactions_test.go @@ -15,6 +15,10 @@ import ( "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/methods" ) +const ( + Cursor int64 = 55834574848 +) + // buildTxParams constructs the parameters necessary for creating a transaction from the given account. // // account - the source account from which the transaction will originate. This account provides the starting sequence number. @@ -134,7 +138,7 @@ func TestGetTransactions(t *testing.T) { assert.Equal(t, result.Transactions[0].LedgerSequence, ledgers[0]) // Get transactions using previous result's cursor - cursor := toid.Parse(55834574848) + cursor := toid.Parse(Cursor) request = methods.GetTransactionsRequest{ EndLedger: ledgers[2], Pagination: &methods.TransactionsPaginationOptions{ From 850f2084392ac167a10c3a8078fed63147cdc5b4 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Fri, 3 May 2024 11:10:03 -0400 Subject: [PATCH 34/57] Remove startLedger check --- cmd/soroban-rpc/internal/methods/get_transactions.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index d1aad9cc..fad5f52e 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -41,9 +41,7 @@ func (req GetTransactionsRequest) isValid(maxLimit uint) error { // Validate pagination if req.Pagination != nil && req.Pagination.Cursor != nil { - if req.StartLedger != 0 { - return errors.New("startLedger and cursor cannot both be set") - } + return errors.New("startLedger and cursor cannot both be set") } if req.Pagination != nil && req.Pagination.Limit > maxLimit { return fmt.Errorf("limit must not exceed %d", maxLimit) From be21a9592e52f03e8b7bad6b7047878c9002325c Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Fri, 3 May 2024 13:22:40 -0400 Subject: [PATCH 35/57] Remove endLedger --- .../internal/methods/get_transactions.go | 30 +++-- .../internal/methods/get_transactions_test.go | 115 +++++++++--------- .../internal/test/get_transactions_test.go | 65 +++++----- 3 files changed, 107 insertions(+), 103 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index fad5f52e..4930cad6 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -24,24 +24,19 @@ type TransactionsPaginationOptions struct { // GetTransactionsRequest represents the request parameters for fetching transactions within a range of ledgers. type GetTransactionsRequest struct { StartLedger uint32 `json:"startLedger"` - EndLedger uint32 `json:"endLedger"` Pagination *TransactionsPaginationOptions `json:"pagination,omitempty"` } // isValid checks the validity of the request parameters. // It returns an error if any parameter is out of the expected range or combination. func (req GetTransactionsRequest) isValid(maxLimit uint) error { - // Validate the start and end ledger sequence - if req.StartLedger < 0 { - return errors.New("start ledger cannot be negative") - } - if req.EndLedger < req.StartLedger { - return errors.New("end ledger cannot be less than start ledger") - } - - // Validate pagination + // Validate pagination and start ledger sequence if req.Pagination != nil && req.Pagination.Cursor != nil { - return errors.New("startLedger and cursor cannot both be set") + if req.StartLedger != 0 { + return errors.New("startLedger and cursor cannot both be set") + } + } else if req.StartLedger <= 1 { + return errors.New("start ledger cannot be negative") } if req.Pagination != nil && req.Pagination.Limit > maxLimit { return fmt.Errorf("limit must not exceed %d", maxLimit) @@ -66,6 +61,8 @@ type GetTransactionsResponse struct { Transactions []transactionInfo `json:"transactions"` LatestLedger int64 `json:"latestLedger"` LatestLedgerCloseTimestamp int64 `json:"latestLedgerCloseTimestamp"` + OldestLedger int64 `json:"oldestLedger"` + OldestLedgerCloseTimestamp int64 `json:"oldestLedgerCloseTimestamp"` Cursor string `json:"cursor"` } @@ -104,11 +101,20 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont } } + // The latest ledger acts as the end ledger range for the request. + latestLedgerSequence, _, err := h.getLatestLedgerDetails(ctx) + if err != nil { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } + } + // Iterate through each ledger and its transactions until limit or end range is reached var txns []transactionInfo var cursor *toid.ID LedgerLoop: - for ledgerSeq := start.LedgerSequence; ledgerSeq <= int32(request.EndLedger); ledgerSeq++ { + for ledgerSeq := start.LedgerSequence; ledgerSeq <= int32(latestLedgerSequence); ledgerSeq++ { // Get ledger close meta from db ledger, found, err := h.ledgerReader.GetLedger(ctx, uint32(ledgerSeq)) if (err != nil) || (!found) { diff --git a/cmd/soroban-rpc/internal/methods/get_transactions_test.go b/cmd/soroban-rpc/internal/methods/get_transactions_test.go index 8eafa16c..863d50a8 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions_test.go @@ -14,9 +14,7 @@ import ( ) const ( - NetworkPassphrase string = "passphrase" - LatestLedger int64 = 1136657 - LatestLedgerCloseTimestamp int64 = 28419025 + NetworkPassphrase string = "passphrase" ) // createTestLedger Creates a test ledger with 2 transactions @@ -37,14 +35,14 @@ func createTestLedger(sequence uint32) xdr.LedgerCloseMeta { } // getMockReaders build mock readers for interfaces - LedgerReader, LedgerEntryReader. -func getMockReaders(ctrl *gomock.Controller, ledgerFound bool, err error) (*util.MockLedgerEntryReader, *util.MockLedgerReader) { +func getMockReaders(ctrl *gomock.Controller, ledgerFound bool, latestLedger int64, err error) (*util.MockLedgerEntryReader, *util.MockLedgerReader) { mockLedgerReader := util.NewMockLedgerReader(ctrl) mockLedgerReader.EXPECT(). GetLedger(gomock.Any(), gomock.Any()). DoAndReturn(func(ctx context.Context, sequence uint32) (xdr.LedgerCloseMeta, bool, error) { var meta xdr.LedgerCloseMeta if ledgerFound { - meta = createTestLedger(sequence) + meta = createTestLedger(sequence - 100) } return meta, ledgerFound, err }).AnyTimes() @@ -52,7 +50,7 @@ func getMockReaders(ctrl *gomock.Controller, ledgerFound bool, err error) (*util mockLedgerEntryReader := util.NewMockLedgerEntryReader(ctrl) mockLedgerEntryReader.EXPECT(). GetLatestLedgerSequence(gomock.Any()). - Return(uint32(LatestLedger), nil).AnyTimes() + Return(uint32(latestLedger), nil).AnyTimes() return mockLedgerEntryReader, mockLedgerReader } @@ -61,7 +59,7 @@ func TestGetTransactions_DefaultLimit(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, nil) + mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, 10, nil) handler := transactionsRPCHandler{ ledgerReader: mockLedgerReader, @@ -73,28 +71,27 @@ func TestGetTransactions_DefaultLimit(t *testing.T) { request := GetTransactionsRequest{ StartLedger: 1, - EndLedger: 2, } response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) assert.NoError(t, err) // assert latest ledger details - assert.Equal(t, response.LatestLedger, LatestLedger) - assert.Equal(t, response.LatestLedgerCloseTimestamp, LatestLedgerCloseTimestamp) + assert.Equal(t, response.LatestLedger, int64(10)) + assert.Equal(t, response.LatestLedgerCloseTimestamp, int64(350)) // assert pagination - assert.Equal(t, response.Cursor, toid.New(102, 1, 0).String()) + assert.Equal(t, response.Cursor, toid.New(5, 1, 0).String()) // assert transactions result - assert.Equal(t, len(response.Transactions), 4) + assert.Equal(t, len(response.Transactions), 10) } -func TestGetTransactions_CustomLimit(t *testing.T) { +func TestGetTransactions_DefaultLimitExceedsLatestLedger(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, nil) + mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, 3, nil) handler := transactionsRPCHandler{ ledgerReader: mockLedgerReader, @@ -106,34 +103,27 @@ func TestGetTransactions_CustomLimit(t *testing.T) { request := GetTransactionsRequest{ StartLedger: 1, - EndLedger: 2, - Pagination: &TransactionsPaginationOptions{ - Limit: 2, - }, } response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) assert.NoError(t, err) // assert latest ledger details - assert.Equal(t, response.LatestLedger, LatestLedger) - assert.Equal(t, response.LatestLedgerCloseTimestamp, LatestLedgerCloseTimestamp) + assert.Equal(t, response.LatestLedger, int64(3)) + assert.Equal(t, response.LatestLedgerCloseTimestamp, int64(175)) // assert pagination - assert.Equal(t, response.Cursor, toid.New(101, 1, 0).String()) + assert.Equal(t, response.Cursor, toid.New(3, 1, 0).String()) // assert transactions result - assert.Equal(t, len(response.Transactions), 2) - assert.Equal(t, int(response.Transactions[0].LedgerSequence), 101) - assert.Equal(t, int(response.Transactions[1].LedgerSequence), 101) - + assert.Equal(t, len(response.Transactions), 6) } -func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { +func TestGetTransactions_CustomLimit(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, nil) + mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, 10, nil) handler := transactionsRPCHandler{ ledgerReader: mockLedgerReader, @@ -144,13 +134,8 @@ func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { } request := GetTransactionsRequest{ - EndLedger: 2, + StartLedger: 1, Pagination: &TransactionsPaginationOptions{ - Cursor: &toid.ID{ - LedgerSequence: 1, - TransactionOrder: 0, - OperationOrder: 0, - }, Limit: 2, }, } @@ -159,23 +144,23 @@ func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { assert.NoError(t, err) // assert latest ledger details - assert.Equal(t, response.LatestLedger, LatestLedger) - assert.Equal(t, response.LatestLedgerCloseTimestamp, LatestLedgerCloseTimestamp) + assert.Equal(t, response.LatestLedger, int64(10)) + assert.Equal(t, response.LatestLedgerCloseTimestamp, int64(350)) // assert pagination - assert.Equal(t, response.Cursor, toid.New(102, 0, 0).String()) + assert.Equal(t, response.Cursor, toid.New(1, 1, 0).String()) // assert transactions result assert.Equal(t, len(response.Transactions), 2) - assert.Equal(t, int(response.Transactions[0].LedgerSequence), 101) - assert.Equal(t, int(response.Transactions[1].LedgerSequence), 102) + assert.Equal(t, int(response.Transactions[0].LedgerSequence), 1) + assert.Equal(t, int(response.Transactions[1].LedgerSequence), 1) } -func TestGetTransactions_LedgerNotFound(t *testing.T) { +func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, false, nil) + mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, 10, nil) handler := transactionsRPCHandler{ ledgerReader: mockLedgerReader, @@ -186,21 +171,38 @@ func TestGetTransactions_LedgerNotFound(t *testing.T) { } request := GetTransactionsRequest{ - StartLedger: 1, - EndLedger: 2, + Pagination: &TransactionsPaginationOptions{ + Cursor: &toid.ID{ + LedgerSequence: 1, + TransactionOrder: 1, + OperationOrder: 0, + }, + Limit: 3, + }, } response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) - assert.Equal(t, err.Error(), "[-32602] ledger close meta not found: 1") - assert.Nil(t, response.Transactions) + assert.NoError(t, err) + + // assert latest ledger details + assert.Equal(t, response.LatestLedger, int64(10)) + assert.Equal(t, response.LatestLedgerCloseTimestamp, int64(350)) + + // assert pagination + assert.Equal(t, response.Cursor, toid.New(3, 0, 0).String()) + + // assert transactions result + assert.Equal(t, len(response.Transactions), 3) + assert.Equal(t, int(response.Transactions[0].LedgerSequence), 2) + assert.Equal(t, int(response.Transactions[1].LedgerSequence), 2) + assert.Equal(t, int(response.Transactions[2].LedgerSequence), 3) } -func TestGetTransactions_LedgerDbError(t *testing.T) { +func TestGetTransactions_LedgerNotFound(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - err := errors.New("error reading from db") - mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, false, err) + mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, false, 10, nil) handler := transactionsRPCHandler{ ledgerReader: mockLedgerReader, @@ -212,19 +214,19 @@ func TestGetTransactions_LedgerDbError(t *testing.T) { request := GetTransactionsRequest{ StartLedger: 1, - EndLedger: 2, } response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) - assert.Equal(t, err.Error(), "[-32602] error reading from db") + assert.Equal(t, err.Error(), "[-32602] ledger close meta not found: 10") assert.Nil(t, response.Transactions) } -func TestGetTransactions_InvalidLedgerRange(t *testing.T) { +func TestGetTransactions_LedgerDbError(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, nil) + err := errors.New("error reading from db") + mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, false, 10, err) handler := transactionsRPCHandler{ ledgerReader: mockLedgerReader, @@ -235,19 +237,19 @@ func TestGetTransactions_InvalidLedgerRange(t *testing.T) { } request := GetTransactionsRequest{ - StartLedger: 3, - EndLedger: 2, + StartLedger: 1, } - _, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) - assert.Equal(t, err.Error(), "[-32602] end ledger cannot be less than start ledger") + response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) + assert.Equal(t, err.Error(), "[-32602] error reading from db") + assert.Nil(t, response.Transactions) } func TestGetTransactions_LimitGreaterThanMaxLimit(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, nil) + mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, 10, nil) handler := transactionsRPCHandler{ ledgerReader: mockLedgerReader, @@ -259,7 +261,6 @@ func TestGetTransactions_LimitGreaterThanMaxLimit(t *testing.T) { request := GetTransactionsRequest{ StartLedger: 1, - EndLedger: 2, Pagination: &TransactionsPaginationOptions{ Limit: 200, }, diff --git a/cmd/soroban-rpc/internal/test/get_transactions_test.go b/cmd/soroban-rpc/internal/test/get_transactions_test.go index f89a6e51..ba636fba 100644 --- a/cmd/soroban-rpc/internal/test/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/test/get_transactions_test.go @@ -8,7 +8,6 @@ import ( "github.com/creachadair/jrpc2" "github.com/creachadair/jrpc2/jhttp" "github.com/stellar/go/keypair" - "github.com/stellar/go/toid" "github.com/stellar/go/txnbuild" "github.com/stretchr/testify/assert" @@ -105,7 +104,6 @@ func TestGetTransactions(t *testing.T) { var result methods.GetTransactionsResponse request := methods.GetTransactionsRequest{ StartLedger: ledgers[0], - EndLedger: ledgers[2], } err := client.CallResult(context.Background(), "getTransactions", request, &result) assert.NoError(t, err) @@ -115,40 +113,39 @@ func TestGetTransactions(t *testing.T) { assert.Equal(t, result.Transactions[2].LedgerSequence, ledgers[2]) // Get transactions from single ledger - request = methods.GetTransactionsRequest{ - StartLedger: ledgers[0], - EndLedger: ledgers[0], - } - err = client.CallResult(context.Background(), "getTransactions", request, &result) - assert.NoError(t, err) - assert.Equal(t, len(result.Transactions), 1) - assert.Equal(t, result.Transactions[0].LedgerSequence, ledgers[0]) + //request = methods.GetTransactionsRequest{ + // StartLedger: ledgers[0], + //} + //err = client.CallResult(context.Background(), "getTransactions", request, &result) + //assert.NoError(t, err) + //assert.Equal(t, len(result.Transactions), 3) + //assert.Equal(t, result.Transactions[0].LedgerSequence, ledgers[0]) + //assert.Equal(t, result.Transactions[1].LedgerSequence, ledgers[1]) + //assert.Equal(t, result.Transactions[2].LedgerSequence, ledgers[2]) // Get transactions with limit - request = methods.GetTransactionsRequest{ - StartLedger: ledgers[0], - EndLedger: ledgers[2], - Pagination: &methods.TransactionsPaginationOptions{ - Limit: 1, - }, - } - err = client.CallResult(context.Background(), "getTransactions", request, &result) - assert.NoError(t, err) - assert.Equal(t, len(result.Transactions), 1) - assert.Equal(t, result.Transactions[0].LedgerSequence, ledgers[0]) + //request = methods.GetTransactionsRequest{ + // StartLedger: ledgers[0], + // Pagination: &methods.TransactionsPaginationOptions{ + // Limit: 1, + // }, + //} + //err = client.CallResult(context.Background(), "getTransactions", request, &result) + //assert.NoError(t, err) + //assert.Equal(t, len(result.Transactions), 1) + //assert.Equal(t, result.Transactions[0].LedgerSequence, ledgers[0]) // Get transactions using previous result's cursor - cursor := toid.Parse(Cursor) - request = methods.GetTransactionsRequest{ - EndLedger: ledgers[2], - Pagination: &methods.TransactionsPaginationOptions{ - Cursor: &cursor, - Limit: 5, - }, - } - err = client.CallResult(context.Background(), "getTransactions", request, &result) - assert.NoError(t, err) - assert.Equal(t, len(result.Transactions), 2) - assert.Equal(t, result.Transactions[0].LedgerSequence, ledgers[1]) - assert.Equal(t, result.Transactions[1].LedgerSequence, ledgers[2]) + //cursor := toid.Parse(Cursor) + //request = methods.GetTransactionsRequest{ + // Pagination: &methods.TransactionsPaginationOptions{ + // Cursor: &cursor, + // Limit: 5, + // }, + //} + //err = client.CallResult(context.Background(), "getTransactions", request, &result) + //assert.NoError(t, err) + //assert.Equal(t, len(result.Transactions), 2) + //assert.Equal(t, result.Transactions[0].LedgerSequence, ledgers[1]) + //assert.Equal(t, result.Transactions[1].LedgerSequence, ledgers[2]) } From 088dff0a004d03fd4c69e1670e97587de36972ce Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Fri, 3 May 2024 13:29:54 -0400 Subject: [PATCH 36/57] Import fix --- cmd/soroban-rpc/internal/jsonrpc.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/soroban-rpc/internal/jsonrpc.go b/cmd/soroban-rpc/internal/jsonrpc.go index c2d097c7..02b891b4 100644 --- a/cmd/soroban-rpc/internal/jsonrpc.go +++ b/cmd/soroban-rpc/internal/jsonrpc.go @@ -22,7 +22,6 @@ import ( "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/events" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/methods" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/network" - "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/transactions" ) // maxHTTPRequestSize defines the largest request size that the http handler From 74e29419b6a1ba669c0957fc1e186a7ca4be9e45 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Fri, 3 May 2024 13:44:38 -0400 Subject: [PATCH 37/57] Fix failing tests --- cmd/soroban-rpc/internal/methods/get_transactions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 4930cad6..ababc08e 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -35,7 +35,7 @@ func (req GetTransactionsRequest) isValid(maxLimit uint) error { if req.StartLedger != 0 { return errors.New("startLedger and cursor cannot both be set") } - } else if req.StartLedger <= 1 { + } else if req.StartLedger < 1 { return errors.New("start ledger cannot be negative") } if req.Pagination != nil && req.Pagination.Limit > maxLimit { From ca6c4ca8169c68eb13a3d87048ead501fc6e25d1 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Fri, 3 May 2024 17:59:14 -0400 Subject: [PATCH 38/57] Refactor to use new transaction db --- cmd/soroban-rpc/internal/db/mock_ledger.go | 26 ++ .../internal/db/mock_transaction.go | 20 +- cmd/soroban-rpc/internal/jsonrpc.go | 2 +- .../internal/methods/get_transactions.go | 63 +-- .../internal/methods/get_transactions_test.go | 406 +++++++++--------- cmd/soroban-rpc/internal/util/mocks.go | 133 ------ go.mod | 1 - go.sum | 9 - 8 files changed, 251 insertions(+), 409 deletions(-) create mode 100644 cmd/soroban-rpc/internal/db/mock_ledger.go delete mode 100644 cmd/soroban-rpc/internal/util/mocks.go diff --git a/cmd/soroban-rpc/internal/db/mock_ledger.go b/cmd/soroban-rpc/internal/db/mock_ledger.go new file mode 100644 index 00000000..4c538256 --- /dev/null +++ b/cmd/soroban-rpc/internal/db/mock_ledger.go @@ -0,0 +1,26 @@ +package db + +import ( + "context" + + "github.com/stellar/go/xdr" +) + +type mockLedgerReader struct { + txn mockTransactionHandler +} + +func NewMockLedgerReader(txn *mockTransactionHandler) *mockLedgerReader { + return &mockLedgerReader{ + txn: *txn, + } +} + +func (m *mockLedgerReader) GetLedger(ctx context.Context, sequence uint32) (xdr.LedgerCloseMeta, bool, error) { + lcm := m.txn.ledgerSeqToMeta[sequence] + return *lcm, true, nil +} + +func (m *mockLedgerReader) StreamAllLedgers(ctx context.Context, f StreamLedgerFn) error { + return nil +} diff --git a/cmd/soroban-rpc/internal/db/mock_transaction.go b/cmd/soroban-rpc/internal/db/mock_transaction.go index 4cfb4a63..8154edf0 100644 --- a/cmd/soroban-rpc/internal/db/mock_transaction.go +++ b/cmd/soroban-rpc/internal/db/mock_transaction.go @@ -15,20 +15,24 @@ import ( type mockTransactionHandler struct { passphrase string - ledgerRange ledgerbucketwindow.LedgerRange - txs map[string]ingest.LedgerTransaction - ledgers map[string]*xdr.LedgerCloseMeta + ledgerRange ledgerbucketwindow.LedgerRange + txs map[string]ingest.LedgerTransaction + txHashToMeta map[string]*xdr.LedgerCloseMeta + ledgerSeqToMeta map[uint32]*xdr.LedgerCloseMeta } func NewMockTransactionStore(passphrase string) *mockTransactionHandler { return &mockTransactionHandler{ - passphrase: passphrase, - txs: make(map[string]ingest.LedgerTransaction), - ledgers: make(map[string]*xdr.LedgerCloseMeta), + passphrase: passphrase, + txs: make(map[string]ingest.LedgerTransaction), + txHashToMeta: make(map[string]*xdr.LedgerCloseMeta), + ledgerSeqToMeta: make(map[uint32]*xdr.LedgerCloseMeta), } } func (txn *mockTransactionHandler) InsertTransactions(lcm xdr.LedgerCloseMeta) error { + txn.ledgerSeqToMeta[lcm.LedgerSequence()] = &lcm + reader, err := ingest.NewLedgerTransactionReaderFromLedgerCloseMeta(txn.passphrase, lcm) if err != nil { return err @@ -44,7 +48,7 @@ func (txn *mockTransactionHandler) InsertTransactions(lcm xdr.LedgerCloseMeta) e h := tx.Result.TransactionHash.HexString() txn.txs[h] = tx - txn.ledgers[h] = &lcm + txn.txHashToMeta[h] = &lcm } if lcmSeq := lcm.LedgerSequence(); lcmSeq < txn.ledgerRange.FirstLedger.Sequence || @@ -72,7 +76,7 @@ func (txn *mockTransactionHandler) GetTransaction(ctx context.Context, hash xdr. if tx, ok := txn.txs[hash.HexString()]; !ok { return Transaction{}, txn.ledgerRange, ErrNoTransaction } else { - itx, err := ParseTransaction(*txn.ledgers[hash.HexString()], tx) + itx, err := ParseTransaction(*txn.txHashToMeta[hash.HexString()], tx) return itx, txn.ledgerRange, err } } diff --git a/cmd/soroban-rpc/internal/jsonrpc.go b/cmd/soroban-rpc/internal/jsonrpc.go index 02b891b4..03e0cad7 100644 --- a/cmd/soroban-rpc/internal/jsonrpc.go +++ b/cmd/soroban-rpc/internal/jsonrpc.go @@ -206,7 +206,7 @@ func NewJSONRPCHandler(cfg *config.Config, params HandlerParams) Handler { }, { methodName: "getTransactions", - underlyingHandler: methods.NewGetTransactionsHandler(params.Logger, params.LedgerReader, params.LedgerEntryReader, cfg.MaxTransactionsLimit, cfg.DefaultTransactionsLimit, cfg.NetworkPassphrase), + underlyingHandler: methods.NewGetTransactionsHandler(params.Logger, params.LedgerReader, params.TransactionReader, cfg.MaxTransactionsLimit, cfg.DefaultTransactionsLimit, cfg.NetworkPassphrase), longName: "get_transactions", queueLimit: cfg.RequestBacklogSendTransactionQueueLimit, requestDurationLimit: cfg.MaxSendTransactionExecutionDuration, diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index ababc08e..83df1205 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -58,17 +58,17 @@ type transactionInfo struct { // GetTransactionsResponse encapsulates the response structure for getTransactions queries. type GetTransactionsResponse struct { - Transactions []transactionInfo `json:"transactions"` - LatestLedger int64 `json:"latestLedger"` - LatestLedgerCloseTimestamp int64 `json:"latestLedgerCloseTimestamp"` - OldestLedger int64 `json:"oldestLedger"` - OldestLedgerCloseTimestamp int64 `json:"oldestLedgerCloseTimestamp"` - Cursor string `json:"cursor"` + Transactions []transactionInfo `json:"transactions"` + LatestLedger uint32 `json:"latestLedger"` + LatestLedgerCloseTime int64 `json:"latestLedgerCloseTimestamp"` + OldestLedger uint32 `json:"oldestLedger"` + OldestLedgerCloseTime int64 `json:"oldestLedgerCloseTimestamp"` + Cursor string `json:"cursor"` } type transactionsRPCHandler struct { ledgerReader db.LedgerReader - ledgerEntryReader db.LedgerEntryReader + dbReader db.TransactionReader maxLimit uint defaultLimit uint logger *log.Entry @@ -101,8 +101,7 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont } } - // The latest ledger acts as the end ledger range for the request. - latestLedgerSequence, _, err := h.getLatestLedgerDetails(ctx) + ledgerRange, err := h.dbReader.GetLedgerRange(ctx) if err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, @@ -110,11 +109,12 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont } } - // Iterate through each ledger and its transactions until limit or end range is reached + // Iterate through each ledger and its transactions until limit or end range is reached. + // The latest ledger acts as the end ledger range for the request. var txns []transactionInfo var cursor *toid.ID LedgerLoop: - for ledgerSeq := start.LedgerSequence; ledgerSeq <= int32(latestLedgerSequence); ledgerSeq++ { + for ledgerSeq := start.LedgerSequence; ledgerSeq <= int32(ledgerRange.LastLedger.Sequence); ledgerSeq++ { // Get ledger close meta from db ledger, found, err := h.ledgerReader.GetLedger(ctx, uint32(ledgerSeq)) if (err != nil) || (!found) { @@ -190,21 +190,14 @@ LedgerLoop: } } - latestLedgerSequence, latestLedgerCloseTime, err := h.getLatestLedgerDetails(ctx) - if err != nil { - return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, - Message: err.Error(), - } - } - return GetTransactionsResponse{ - Transactions: txns, - LatestLedger: latestLedgerSequence, - LatestLedgerCloseTimestamp: latestLedgerCloseTime, - Cursor: cursor.String(), + Transactions: txns, + LatestLedger: ledgerRange.LastLedger.Sequence, + LatestLedgerCloseTime: ledgerRange.LastLedger.CloseTime, + OldestLedger: ledgerRange.FirstLedger.Sequence, + OldestLedgerCloseTime: ledgerRange.FirstLedger.CloseTime, + Cursor: cursor.String(), }, nil - } // getTransactionDetails fetches XDR for the following transaction details - result, meta and envelope. @@ -225,28 +218,10 @@ func (h transactionsRPCHandler) getTransactionDetails(tx ingest.LedgerTransactio return txResult, txMeta, txEnvelope, nil } -// getLatestLedgerDetails fetches the latest ledger sequence and close time. -func (h transactionsRPCHandler) getLatestLedgerDetails(ctx context.Context) (sequence int64, ledgerCloseTime int64, err error) { - latestSequence, err := h.ledgerEntryReader.GetLatestLedgerSequence(ctx) - if err != nil { - return 0, 0, err - } - - latestLedger, found, err := h.ledgerReader.GetLedger(ctx, latestSequence) - if (err != nil) || (!found) { - if err == nil { - err = errors.Errorf("ledger close meta not found: %d", latestSequence) - } - return 0, 0, err - } - - return int64(latestSequence), latestLedger.LedgerCloseTime(), nil -} - -func NewGetTransactionsHandler(logger *log.Entry, ledgerReader db.LedgerReader, ledgerEntryReader db.LedgerEntryReader, maxLimit, defaultLimit uint, networkPassphrase string) jrpc2.Handler { +func NewGetTransactionsHandler(logger *log.Entry, ledgerReader db.LedgerReader, dbReader db.TransactionReader, maxLimit, defaultLimit uint, networkPassphrase string) jrpc2.Handler { transactionsHandler := transactionsRPCHandler{ ledgerReader: ledgerReader, - ledgerEntryReader: ledgerEntryReader, + dbReader: dbReader, maxLimit: maxLimit, defaultLimit: defaultLimit, logger: logger, diff --git a/cmd/soroban-rpc/internal/methods/get_transactions_test.go b/cmd/soroban-rpc/internal/methods/get_transactions_test.go index 863d50a8..fd728bc1 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions_test.go @@ -4,13 +4,11 @@ import ( "context" "testing" - "github.com/golang/mock/gomock" - "github.com/stellar/go/support/errors" "github.com/stellar/go/toid" "github.com/stellar/go/xdr" "github.com/stretchr/testify/assert" - "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/util" + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/db" ) const ( @@ -34,36 +32,18 @@ func createTestLedger(sequence uint32) xdr.LedgerCloseMeta { return meta } -// getMockReaders build mock readers for interfaces - LedgerReader, LedgerEntryReader. -func getMockReaders(ctrl *gomock.Controller, ledgerFound bool, latestLedger int64, err error) (*util.MockLedgerEntryReader, *util.MockLedgerReader) { - mockLedgerReader := util.NewMockLedgerReader(ctrl) - mockLedgerReader.EXPECT(). - GetLedger(gomock.Any(), gomock.Any()). - DoAndReturn(func(ctx context.Context, sequence uint32) (xdr.LedgerCloseMeta, bool, error) { - var meta xdr.LedgerCloseMeta - if ledgerFound { - meta = createTestLedger(sequence - 100) - } - return meta, ledgerFound, err - }).AnyTimes() - - mockLedgerEntryReader := util.NewMockLedgerEntryReader(ctrl) - mockLedgerEntryReader.EXPECT(). - GetLatestLedgerSequence(gomock.Any()). - Return(uint32(latestLedger), nil).AnyTimes() - - return mockLedgerEntryReader, mockLedgerReader -} - func TestGetTransactions_DefaultLimit(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, 10, nil) + mockDbReader := db.NewMockTransactionStore(NetworkPassphrase) + for i := 1; i <= 10; i++ { + meta := createTestLedger(uint32(i - 100)) + err := mockDbReader.InsertTransactions(meta) + assert.NoError(t, err) + } + mockLedgerReader := db.NewMockLedgerReader(mockDbReader) handler := transactionsRPCHandler{ ledgerReader: mockLedgerReader, - ledgerEntryReader: mockLedgerEntryReader, + dbReader: mockDbReader, maxLimit: 100, defaultLimit: 10, networkPassphrase: NetworkPassphrase, @@ -77,8 +57,8 @@ func TestGetTransactions_DefaultLimit(t *testing.T) { assert.NoError(t, err) // assert latest ledger details - assert.Equal(t, response.LatestLedger, int64(10)) - assert.Equal(t, response.LatestLedgerCloseTimestamp, int64(350)) + assert.Equal(t, response.LatestLedger, uint32(10)) + assert.Equal(t, response.LatestLedgerCloseTime, int64(350)) // assert pagination assert.Equal(t, response.Cursor, toid.New(5, 1, 0).String()) @@ -87,185 +67,185 @@ func TestGetTransactions_DefaultLimit(t *testing.T) { assert.Equal(t, len(response.Transactions), 10) } -func TestGetTransactions_DefaultLimitExceedsLatestLedger(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, 3, nil) - - handler := transactionsRPCHandler{ - ledgerReader: mockLedgerReader, - ledgerEntryReader: mockLedgerEntryReader, - maxLimit: 100, - defaultLimit: 10, - networkPassphrase: NetworkPassphrase, - } - - request := GetTransactionsRequest{ - StartLedger: 1, - } - - response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) - assert.NoError(t, err) - - // assert latest ledger details - assert.Equal(t, response.LatestLedger, int64(3)) - assert.Equal(t, response.LatestLedgerCloseTimestamp, int64(175)) - - // assert pagination - assert.Equal(t, response.Cursor, toid.New(3, 1, 0).String()) - - // assert transactions result - assert.Equal(t, len(response.Transactions), 6) -} - -func TestGetTransactions_CustomLimit(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, 10, nil) - - handler := transactionsRPCHandler{ - ledgerReader: mockLedgerReader, - ledgerEntryReader: mockLedgerEntryReader, - maxLimit: 100, - defaultLimit: 10, - networkPassphrase: NetworkPassphrase, - } - - request := GetTransactionsRequest{ - StartLedger: 1, - Pagination: &TransactionsPaginationOptions{ - Limit: 2, - }, - } - - response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) - assert.NoError(t, err) - - // assert latest ledger details - assert.Equal(t, response.LatestLedger, int64(10)) - assert.Equal(t, response.LatestLedgerCloseTimestamp, int64(350)) - - // assert pagination - assert.Equal(t, response.Cursor, toid.New(1, 1, 0).String()) - - // assert transactions result - assert.Equal(t, len(response.Transactions), 2) - assert.Equal(t, int(response.Transactions[0].LedgerSequence), 1) - assert.Equal(t, int(response.Transactions[1].LedgerSequence), 1) -} - -func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, 10, nil) - - handler := transactionsRPCHandler{ - ledgerReader: mockLedgerReader, - ledgerEntryReader: mockLedgerEntryReader, - maxLimit: 100, - defaultLimit: 10, - networkPassphrase: NetworkPassphrase, - } - - request := GetTransactionsRequest{ - Pagination: &TransactionsPaginationOptions{ - Cursor: &toid.ID{ - LedgerSequence: 1, - TransactionOrder: 1, - OperationOrder: 0, - }, - Limit: 3, - }, - } - - response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) - assert.NoError(t, err) - - // assert latest ledger details - assert.Equal(t, response.LatestLedger, int64(10)) - assert.Equal(t, response.LatestLedgerCloseTimestamp, int64(350)) - - // assert pagination - assert.Equal(t, response.Cursor, toid.New(3, 0, 0).String()) - - // assert transactions result - assert.Equal(t, len(response.Transactions), 3) - assert.Equal(t, int(response.Transactions[0].LedgerSequence), 2) - assert.Equal(t, int(response.Transactions[1].LedgerSequence), 2) - assert.Equal(t, int(response.Transactions[2].LedgerSequence), 3) -} - -func TestGetTransactions_LedgerNotFound(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, false, 10, nil) - - handler := transactionsRPCHandler{ - ledgerReader: mockLedgerReader, - ledgerEntryReader: mockLedgerEntryReader, - maxLimit: 100, - defaultLimit: 10, - networkPassphrase: NetworkPassphrase, - } - - request := GetTransactionsRequest{ - StartLedger: 1, - } - - response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) - assert.Equal(t, err.Error(), "[-32602] ledger close meta not found: 10") - assert.Nil(t, response.Transactions) -} - -func TestGetTransactions_LedgerDbError(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - err := errors.New("error reading from db") - mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, false, 10, err) - - handler := transactionsRPCHandler{ - ledgerReader: mockLedgerReader, - ledgerEntryReader: mockLedgerEntryReader, - maxLimit: 100, - defaultLimit: 10, - networkPassphrase: NetworkPassphrase, - } - - request := GetTransactionsRequest{ - StartLedger: 1, - } - - response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) - assert.Equal(t, err.Error(), "[-32602] error reading from db") - assert.Nil(t, response.Transactions) -} - -func TestGetTransactions_LimitGreaterThanMaxLimit(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, 10, nil) - - handler := transactionsRPCHandler{ - ledgerReader: mockLedgerReader, - ledgerEntryReader: mockLedgerEntryReader, - maxLimit: 100, - defaultLimit: 10, - networkPassphrase: NetworkPassphrase, - } - - request := GetTransactionsRequest{ - StartLedger: 1, - Pagination: &TransactionsPaginationOptions{ - Limit: 200, - }, - } - - _, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) - assert.Equal(t, err.Error(), "[-32602] limit must not exceed 100") -} +//func TestGetTransactions_DefaultLimitExceedsLatestLedger(t *testing.T) { +// ctrl := gomock.NewController(t) +// defer ctrl.Finish() +// +// mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, 3, nil) +// +// handler := transactionsRPCHandler{ +// ledgerReader: mockLedgerReader, +// ledgerEntryReader: mockLedgerEntryReader, +// maxLimit: 100, +// defaultLimit: 10, +// networkPassphrase: NetworkPassphrase, +// } +// +// request := GetTransactionsRequest{ +// StartLedger: 1, +// } +// +// response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) +// assert.NoError(t, err) +// +// // assert latest ledger details +// assert.Equal(t, response.LatestLedger, int64(3)) +// assert.Equal(t, response.LatestLedgerCloseTimestamp, int64(175)) +// +// // assert pagination +// assert.Equal(t, response.Cursor, toid.New(3, 1, 0).String()) +// +// // assert transactions result +// assert.Equal(t, len(response.Transactions), 6) +//} +// +//func TestGetTransactions_CustomLimit(t *testing.T) { +// ctrl := gomock.NewController(t) +// defer ctrl.Finish() +// +// mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, 10, nil) +// +// handler := transactionsRPCHandler{ +// ledgerReader: mockLedgerReader, +// ledgerEntryReader: mockLedgerEntryReader, +// maxLimit: 100, +// defaultLimit: 10, +// networkPassphrase: NetworkPassphrase, +// } +// +// request := GetTransactionsRequest{ +// StartLedger: 1, +// Pagination: &TransactionsPaginationOptions{ +// Limit: 2, +// }, +// } +// +// response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) +// assert.NoError(t, err) +// +// // assert latest ledger details +// assert.Equal(t, response.LatestLedger, int64(10)) +// assert.Equal(t, response.LatestLedgerCloseTimestamp, int64(350)) +// +// // assert pagination +// assert.Equal(t, response.Cursor, toid.New(1, 1, 0).String()) +// +// // assert transactions result +// assert.Equal(t, len(response.Transactions), 2) +// assert.Equal(t, int(response.Transactions[0].LedgerSequence), 1) +// assert.Equal(t, int(response.Transactions[1].LedgerSequence), 1) +//} +// +//func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { +// ctrl := gomock.NewController(t) +// defer ctrl.Finish() +// +// mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, 10, nil) +// +// handler := transactionsRPCHandler{ +// ledgerReader: mockLedgerReader, +// ledgerEntryReader: mockLedgerEntryReader, +// maxLimit: 100, +// defaultLimit: 10, +// networkPassphrase: NetworkPassphrase, +// } +// +// request := GetTransactionsRequest{ +// Pagination: &TransactionsPaginationOptions{ +// Cursor: &toid.ID{ +// LedgerSequence: 1, +// TransactionOrder: 1, +// OperationOrder: 0, +// }, +// Limit: 3, +// }, +// } +// +// response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) +// assert.NoError(t, err) +// +// // assert latest ledger details +// assert.Equal(t, response.LatestLedger, int64(10)) +// assert.Equal(t, response.LatestLedgerCloseTimestamp, int64(350)) +// +// // assert pagination +// assert.Equal(t, response.Cursor, toid.New(3, 0, 0).String()) +// +// // assert transactions result +// assert.Equal(t, len(response.Transactions), 3) +// assert.Equal(t, int(response.Transactions[0].LedgerSequence), 2) +// assert.Equal(t, int(response.Transactions[1].LedgerSequence), 2) +// assert.Equal(t, int(response.Transactions[2].LedgerSequence), 3) +//} +// +//func TestGetTransactions_LedgerNotFound(t *testing.T) { +// ctrl := gomock.NewController(t) +// defer ctrl.Finish() +// +// mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, false, 10, nil) +// +// handler := transactionsRPCHandler{ +// ledgerReader: mockLedgerReader, +// ledgerEntryReader: mockLedgerEntryReader, +// maxLimit: 100, +// defaultLimit: 10, +// networkPassphrase: NetworkPassphrase, +// } +// +// request := GetTransactionsRequest{ +// StartLedger: 1, +// } +// +// response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) +// assert.Equal(t, err.Error(), "[-32602] ledger close meta not found: 10") +// assert.Nil(t, response.Transactions) +//} +// +//func TestGetTransactions_LedgerDbError(t *testing.T) { +// ctrl := gomock.NewController(t) +// defer ctrl.Finish() +// +// err := errors.New("error reading from db") +// mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, false, 10, err) +// +// handler := transactionsRPCHandler{ +// ledgerReader: mockLedgerReader, +// ledgerEntryReader: mockLedgerEntryReader, +// maxLimit: 100, +// defaultLimit: 10, +// networkPassphrase: NetworkPassphrase, +// } +// +// request := GetTransactionsRequest{ +// StartLedger: 1, +// } +// +// response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) +// assert.Equal(t, err.Error(), "[-32602] error reading from db") +// assert.Nil(t, response.Transactions) +//} +// +//func TestGetTransactions_LimitGreaterThanMaxLimit(t *testing.T) { +// ctrl := gomock.NewController(t) +// defer ctrl.Finish() +// +// mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, 10, nil) +// +// handler := transactionsRPCHandler{ +// ledgerReader: mockLedgerReader, +// ledgerEntryReader: mockLedgerEntryReader, +// maxLimit: 100, +// defaultLimit: 10, +// networkPassphrase: NetworkPassphrase, +// } +// +// request := GetTransactionsRequest{ +// StartLedger: 1, +// Pagination: &TransactionsPaginationOptions{ +// Limit: 200, +// }, +// } +// +// _, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) +// assert.Equal(t, err.Error(), "[-32602] limit must not exceed 100") +//} diff --git a/cmd/soroban-rpc/internal/util/mocks.go b/cmd/soroban-rpc/internal/util/mocks.go deleted file mode 100644 index acfd2d51..00000000 --- a/cmd/soroban-rpc/internal/util/mocks.go +++ /dev/null @@ -1,133 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/db (interfaces: LedgerReader,LedgerEntryReader) -package util - -import ( - context "context" - reflect "reflect" - - gomock "github.com/golang/mock/gomock" - xdr "github.com/stellar/go/xdr" - db "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/db" -) - -// MockLedgerReader is a mock of LedgerReader interface. -type MockLedgerReader struct { - ctrl *gomock.Controller - recorder *MockLedgerReaderMockRecorder -} - -// MockLedgerReaderMockRecorder is the mock recorder for MockLedgerReader. -type MockLedgerReaderMockRecorder struct { - mock *MockLedgerReader -} - -// NewMockLedgerReader creates a new mock instance. -func NewMockLedgerReader(ctrl *gomock.Controller) *MockLedgerReader { - mock := &MockLedgerReader{ctrl: ctrl} - mock.recorder = &MockLedgerReaderMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockLedgerReader) EXPECT() *MockLedgerReaderMockRecorder { - return m.recorder -} - -// GetLedger mocks base method. -func (m *MockLedgerReader) GetLedger(arg0 context.Context, arg1 uint32) (xdr.LedgerCloseMeta, bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetLedger", arg0, arg1) - ret0, _ := ret[0].(xdr.LedgerCloseMeta) - ret1, _ := ret[1].(bool) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// GetLedger indicates an expected call of GetLedger. -func (mr *MockLedgerReaderMockRecorder) GetLedger(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLedger", reflect.TypeOf((*MockLedgerReader)(nil).GetLedger), arg0, arg1) -} - -// StreamAllLedgers mocks base method. -func (m *MockLedgerReader) StreamAllLedgers(arg0 context.Context, arg1 db.StreamLedgerFn) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StreamAllLedgers", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// StreamAllLedgers indicates an expected call of StreamAllLedgers. -func (mr *MockLedgerReaderMockRecorder) StreamAllLedgers(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StreamAllLedgers", reflect.TypeOf((*MockLedgerReader)(nil).StreamAllLedgers), arg0, arg1) -} - -// MockLedgerEntryReader is a mock of LedgerEntryReader interface. -type MockLedgerEntryReader struct { - ctrl *gomock.Controller - recorder *MockLedgerEntryReaderMockRecorder -} - -// MockLedgerEntryReaderMockRecorder is the mock recorder for MockLedgerEntryReader. -type MockLedgerEntryReaderMockRecorder struct { - mock *MockLedgerEntryReader -} - -// NewMockLedgerEntryReader creates a new mock instance. -func NewMockLedgerEntryReader(ctrl *gomock.Controller) *MockLedgerEntryReader { - mock := &MockLedgerEntryReader{ctrl: ctrl} - mock.recorder = &MockLedgerEntryReaderMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockLedgerEntryReader) EXPECT() *MockLedgerEntryReaderMockRecorder { - return m.recorder -} - -// GetLatestLedgerSequence mocks base method. -func (m *MockLedgerEntryReader) GetLatestLedgerSequence(arg0 context.Context) (uint32, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetLatestLedgerSequence", arg0) - ret0, _ := ret[0].(uint32) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetLatestLedgerSequence indicates an expected call of GetLatestLedgerSequence. -func (mr *MockLedgerEntryReaderMockRecorder) GetLatestLedgerSequence(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLatestLedgerSequence", reflect.TypeOf((*MockLedgerEntryReader)(nil).GetLatestLedgerSequence), arg0) -} - -// NewCachedTx mocks base method. -func (m *MockLedgerEntryReader) NewCachedTx(arg0 context.Context) (db.LedgerEntryReadTx, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NewCachedTx", arg0) - ret0, _ := ret[0].(db.LedgerEntryReadTx) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// NewCachedTx indicates an expected call of NewCachedTx. -func (mr *MockLedgerEntryReaderMockRecorder) NewCachedTx(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewCachedTx", reflect.TypeOf((*MockLedgerEntryReader)(nil).NewCachedTx), arg0) -} - -// NewTx mocks base method. -func (m *MockLedgerEntryReader) NewTx(arg0 context.Context) (db.LedgerEntryReadTx, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NewTx", arg0) - ret0, _ := ret[0].(db.LedgerEntryReadTx) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// NewTx indicates an expected call of NewTx. -func (mr *MockLedgerEntryReaderMockRecorder) NewTx(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewTx", reflect.TypeOf((*MockLedgerEntryReader)(nil).NewTx), arg0) -} diff --git a/go.mod b/go.mod index 5736df7a..abc7712d 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,6 @@ require ( github.com/creachadair/jrpc2 v1.2.0 github.com/go-chi/chi v4.1.2+incompatible github.com/go-git/go-git/v5 v5.9.0 - github.com/golang/mock v1.6.0 github.com/mattn/go-sqlite3 v1.14.17 github.com/pelletier/go-toml v1.9.5 github.com/prometheus/client_golang v1.17.0 diff --git a/go.sum b/go.sum index f985f7d8..e8fae23b 100644 --- a/go.sum +++ b/go.sum @@ -175,8 +175,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -419,7 +417,6 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= @@ -491,7 +488,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= @@ -528,7 +524,6 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= @@ -558,7 +553,6 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= @@ -597,10 +591,8 @@ golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -687,7 +679,6 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= From 6d415ddfe99213a66b201f66108680e5827d8681 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Fri, 3 May 2024 18:18:34 -0400 Subject: [PATCH 39/57] Refactor mocks --- cmd/soroban-rpc/internal/db/mock_ledger.go | 26 ------- .../db/{mock_transaction.go => mocks.go} | 20 +++++- .../internal/methods/get_transactions.go | 61 +++------------- .../internal/methods/get_transactions_test.go | 70 ++++++++++--------- .../internal/test/get_transactions_test.go | 6 +- 5 files changed, 68 insertions(+), 115 deletions(-) delete mode 100644 cmd/soroban-rpc/internal/db/mock_ledger.go rename cmd/soroban-rpc/internal/db/{mock_transaction.go => mocks.go} (83%) diff --git a/cmd/soroban-rpc/internal/db/mock_ledger.go b/cmd/soroban-rpc/internal/db/mock_ledger.go deleted file mode 100644 index 4c538256..00000000 --- a/cmd/soroban-rpc/internal/db/mock_ledger.go +++ /dev/null @@ -1,26 +0,0 @@ -package db - -import ( - "context" - - "github.com/stellar/go/xdr" -) - -type mockLedgerReader struct { - txn mockTransactionHandler -} - -func NewMockLedgerReader(txn *mockTransactionHandler) *mockLedgerReader { - return &mockLedgerReader{ - txn: *txn, - } -} - -func (m *mockLedgerReader) GetLedger(ctx context.Context, sequence uint32) (xdr.LedgerCloseMeta, bool, error) { - lcm := m.txn.ledgerSeqToMeta[sequence] - return *lcm, true, nil -} - -func (m *mockLedgerReader) StreamAllLedgers(ctx context.Context, f StreamLedgerFn) error { - return nil -} diff --git a/cmd/soroban-rpc/internal/db/mock_transaction.go b/cmd/soroban-rpc/internal/db/mocks.go similarity index 83% rename from cmd/soroban-rpc/internal/db/mock_transaction.go rename to cmd/soroban-rpc/internal/db/mocks.go index 8154edf0..18676cb5 100644 --- a/cmd/soroban-rpc/internal/db/mock_transaction.go +++ b/cmd/soroban-rpc/internal/db/mocks.go @@ -83,5 +83,21 @@ func (txn *mockTransactionHandler) GetTransaction(ctx context.Context, hash xdr. func (txn *mockTransactionHandler) RegisterMetrics(_, _ prometheus.Observer) {} -var _ TransactionReader = &mockTransactionHandler{} -var _ TransactionWriter = &mockTransactionHandler{} +type mockLedgerReader struct { + txn mockTransactionHandler +} + +func NewMockLedgerReader(txn *mockTransactionHandler) *mockLedgerReader { + return &mockLedgerReader{ + txn: *txn, + } +} + +func (m *mockLedgerReader) GetLedger(ctx context.Context, sequence uint32) (xdr.LedgerCloseMeta, bool, error) { + lcm := m.txn.ledgerSeqToMeta[sequence] + return *lcm, true, nil +} + +func (m *mockLedgerReader) StreamAllLedgers(ctx context.Context, f StreamLedgerFn) error { + return nil +} diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 83df1205..63f3a2ef 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -28,9 +28,7 @@ type GetTransactionsRequest struct { } // isValid checks the validity of the request parameters. -// It returns an error if any parameter is out of the expected range or combination. func (req GetTransactionsRequest) isValid(maxLimit uint) error { - // Validate pagination and start ledger sequence if req.Pagination != nil && req.Pagination.Cursor != nil { if req.StartLedger != 0 { return errors.New("startLedger and cursor cannot both be set") @@ -45,25 +43,14 @@ func (req GetTransactionsRequest) isValid(maxLimit uint) error { return nil } -// transactionInfo represents the decoded transaction information from the ledger close meta. -type transactionInfo struct { - Result []byte `json:"result"` - Meta []byte `json:"meta"` - Envelope []byte `json:"envelope"` - FeeBump bool `json:"feeBump"` - ApplicationOrder int32 `json:"applicationOrder"` - Successful bool `json:"successful"` - LedgerSequence uint32 `json:"ledgerSequence"` -} - // GetTransactionsResponse encapsulates the response structure for getTransactions queries. type GetTransactionsResponse struct { - Transactions []transactionInfo `json:"transactions"` - LatestLedger uint32 `json:"latestLedger"` - LatestLedgerCloseTime int64 `json:"latestLedgerCloseTimestamp"` - OldestLedger uint32 `json:"oldestLedger"` - OldestLedgerCloseTime int64 `json:"oldestLedgerCloseTimestamp"` - Cursor string `json:"cursor"` + Transactions []db.Transaction `json:"transactions"` + LatestLedger uint32 `json:"latestLedger"` + LatestLedgerCloseTime int64 `json:"latestLedgerCloseTimestamp"` + OldestLedger uint32 `json:"oldestLedger"` + OldestLedgerCloseTime int64 `json:"oldestLedgerCloseTimestamp"` + Cursor string `json:"cursor"` } type transactionsRPCHandler struct { @@ -111,7 +98,7 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont // Iterate through each ledger and its transactions until limit or end range is reached. // The latest ledger acts as the end ledger range for the request. - var txns []transactionInfo + var txns []db.Transaction var cursor *toid.ID LedgerLoop: for ledgerSeq := start.LedgerSequence; ledgerSeq <= int32(ledgerRange.LastLedger.Sequence); ledgerSeq++ { @@ -153,7 +140,7 @@ LedgerLoop: for i := startTxIdx; i < txCount; i++ { cursor = toid.New(int32(ledger.LedgerSequence()), int32(i), 0) - tx, err := reader.Read() + ingestTx, err := reader.Read() if err != nil { if err == io.EOF { // No more transactions to read. Start from next ledger @@ -165,7 +152,7 @@ LedgerLoop: } } - txResult, txMeta, txEnvelope, err := h.getTransactionDetails(tx) + tx, err := db.ParseTransaction(ledger, ingestTx) if err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, @@ -173,17 +160,7 @@ LedgerLoop: } } - txInfo := transactionInfo{ - Result: txResult, - Meta: txMeta, - Envelope: txEnvelope, - FeeBump: tx.Envelope.IsFeeBump(), - ApplicationOrder: int32(tx.Index), - Successful: tx.Result.Result.Successful(), - LedgerSequence: ledger.LedgerSequence(), - } - - txns = append(txns, txInfo) + txns = append(txns, tx) if len(txns) >= int(limit) { break LedgerLoop } @@ -200,24 +177,6 @@ LedgerLoop: }, nil } -// getTransactionDetails fetches XDR for the following transaction details - result, meta and envelope. -func (h transactionsRPCHandler) getTransactionDetails(tx ingest.LedgerTransaction) ([]byte, []byte, []byte, error) { - txResult, err := tx.Result.Result.MarshalBinary() - if err != nil { - return nil, nil, nil, err - } - txMeta, err := tx.UnsafeMeta.MarshalBinary() - if err != nil { - return nil, nil, nil, err - } - txEnvelope, err := tx.Envelope.MarshalBinary() - if err != nil { - return nil, nil, nil, err - } - - return txResult, txMeta, txEnvelope, nil -} - func NewGetTransactionsHandler(logger *log.Entry, ledgerReader db.LedgerReader, dbReader db.TransactionReader, maxLimit, defaultLimit uint, networkPassphrase string) jrpc2.Handler { transactionsHandler := transactionsRPCHandler{ ledgerReader: ledgerReader, diff --git a/cmd/soroban-rpc/internal/methods/get_transactions_test.go b/cmd/soroban-rpc/internal/methods/get_transactions_test.go index fd728bc1..a299ea93 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions_test.go @@ -17,6 +17,7 @@ const ( // createTestLedger Creates a test ledger with 2 transactions func createTestLedger(sequence uint32) xdr.LedgerCloseMeta { + sequence = sequence - 100 meta := txMeta(sequence, true) meta.V1.TxProcessing = append(meta.V1.TxProcessing, xdr.TransactionResultMeta{ TxApplyProcessing: xdr.TransactionMeta{ @@ -35,7 +36,7 @@ func createTestLedger(sequence uint32) xdr.LedgerCloseMeta { func TestGetTransactions_DefaultLimit(t *testing.T) { mockDbReader := db.NewMockTransactionStore(NetworkPassphrase) for i := 1; i <= 10; i++ { - meta := createTestLedger(uint32(i - 100)) + meta := createTestLedger(uint32(i)) err := mockDbReader.InsertTransactions(meta) assert.NoError(t, err) } @@ -67,38 +68,41 @@ func TestGetTransactions_DefaultLimit(t *testing.T) { assert.Equal(t, len(response.Transactions), 10) } -//func TestGetTransactions_DefaultLimitExceedsLatestLedger(t *testing.T) { -// ctrl := gomock.NewController(t) -// defer ctrl.Finish() -// -// mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, 3, nil) -// -// handler := transactionsRPCHandler{ -// ledgerReader: mockLedgerReader, -// ledgerEntryReader: mockLedgerEntryReader, -// maxLimit: 100, -// defaultLimit: 10, -// networkPassphrase: NetworkPassphrase, -// } -// -// request := GetTransactionsRequest{ -// StartLedger: 1, -// } -// -// response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) -// assert.NoError(t, err) -// -// // assert latest ledger details -// assert.Equal(t, response.LatestLedger, int64(3)) -// assert.Equal(t, response.LatestLedgerCloseTimestamp, int64(175)) -// -// // assert pagination -// assert.Equal(t, response.Cursor, toid.New(3, 1, 0).String()) -// -// // assert transactions result -// assert.Equal(t, len(response.Transactions), 6) -//} -// +func TestGetTransactions_DefaultLimitExceedsLatestLedger(t *testing.T) { + mockDbReader := db.NewMockTransactionStore(NetworkPassphrase) + for i := 1; i <= 3; i++ { + meta := createTestLedger(uint32(i)) + err := mockDbReader.InsertTransactions(meta) + assert.NoError(t, err) + } + mockLedgerReader := db.NewMockLedgerReader(mockDbReader) + + handler := transactionsRPCHandler{ + ledgerReader: mockLedgerReader, + dbReader: mockDbReader, + maxLimit: 100, + defaultLimit: 10, + networkPassphrase: NetworkPassphrase, + } + + request := GetTransactionsRequest{ + StartLedger: 1, + } + + response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) + assert.NoError(t, err) + + // assert latest ledger details + assert.Equal(t, response.LatestLedger, uint32(3)) + assert.Equal(t, response.LatestLedgerCloseTime, int64(175)) + + // assert pagination + assert.Equal(t, response.Cursor, toid.New(3, 1, 0).String()) + + // assert transactions result + assert.Equal(t, len(response.Transactions), 6) +} + //func TestGetTransactions_CustomLimit(t *testing.T) { // ctrl := gomock.NewController(t) // defer ctrl.Finish() diff --git a/cmd/soroban-rpc/internal/test/get_transactions_test.go b/cmd/soroban-rpc/internal/test/get_transactions_test.go index ba636fba..3dda9806 100644 --- a/cmd/soroban-rpc/internal/test/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/test/get_transactions_test.go @@ -108,9 +108,9 @@ func TestGetTransactions(t *testing.T) { err := client.CallResult(context.Background(), "getTransactions", request, &result) assert.NoError(t, err) assert.Equal(t, len(result.Transactions), 3) - assert.Equal(t, result.Transactions[0].LedgerSequence, ledgers[0]) - assert.Equal(t, result.Transactions[1].LedgerSequence, ledgers[1]) - assert.Equal(t, result.Transactions[2].LedgerSequence, ledgers[2]) + assert.Equal(t, result.Transactions[0].Ledger.Sequence, ledgers[0]) + assert.Equal(t, result.Transactions[1].Ledger.Sequence, ledgers[1]) + assert.Equal(t, result.Transactions[2].Ledger.Sequence, ledgers[2]) // Get transactions from single ledger //request = methods.GetTransactionsRequest{ From acaae6110c4e88fc2b3456a0516940048df763b1 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Mon, 6 May 2024 11:06:26 -0400 Subject: [PATCH 40/57] Refactor unittests for using the new db changes --- cmd/soroban-rpc/internal/db/mocks.go | 5 +- .../internal/methods/get_transactions.go | 26 +- .../internal/methods/get_transactions_test.go | 322 +++++++++--------- 3 files changed, 188 insertions(+), 165 deletions(-) diff --git a/cmd/soroban-rpc/internal/db/mocks.go b/cmd/soroban-rpc/internal/db/mocks.go index 18676cb5..19c8c142 100644 --- a/cmd/soroban-rpc/internal/db/mocks.go +++ b/cmd/soroban-rpc/internal/db/mocks.go @@ -94,7 +94,10 @@ func NewMockLedgerReader(txn *mockTransactionHandler) *mockLedgerReader { } func (m *mockLedgerReader) GetLedger(ctx context.Context, sequence uint32) (xdr.LedgerCloseMeta, bool, error) { - lcm := m.txn.ledgerSeqToMeta[sequence] + lcm, ok := m.txn.ledgerSeqToMeta[sequence] + if !ok { + return xdr.LedgerCloseMeta{}, false, nil + } return *lcm, true, nil } diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 63f3a2ef..7f582699 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -13,6 +13,7 @@ import ( "github.com/stellar/go/toid" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/db" + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/ledgerbucketwindow" ) // TransactionsPaginationOptions defines the available options for paginating through transactions. @@ -28,14 +29,15 @@ type GetTransactionsRequest struct { } // isValid checks the validity of the request parameters. -func (req GetTransactionsRequest) isValid(maxLimit uint) error { +func (req GetTransactionsRequest) isValid(maxLimit uint, ledgerRange ledgerbucketwindow.LedgerRange) error { if req.Pagination != nil && req.Pagination.Cursor != nil { if req.StartLedger != 0 { return errors.New("startLedger and cursor cannot both be set") } - } else if req.StartLedger < 1 { - return errors.New("start ledger cannot be negative") + } else if req.StartLedger < ledgerRange.FirstLedger.Sequence || req.StartLedger > ledgerRange.LastLedger.Sequence { + return errors.Errorf("start ledger must be between the oldest ledger: %d and the latest ledger: %d for this rpc instance.", ledgerRange.FirstLedger.Sequence, ledgerRange.LastLedger.Sequence) } + if req.Pagination != nil && req.Pagination.Limit > maxLimit { return fmt.Errorf("limit must not exceed %d", maxLimit) } @@ -65,7 +67,15 @@ type transactionsRPCHandler struct { // getTransactionsByLedgerSequence fetches transactions between the start and end ledgers, inclusive of both. // The number of ledgers returned can be tuned using the pagination options - cursor and limit. func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Context, request GetTransactionsRequest) (GetTransactionsResponse, error) { - err := request.isValid(h.maxLimit) + ledgerRange, err := h.dbReader.GetLedgerRange(ctx) + if err != nil { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } + } + + err = request.isValid(h.maxLimit, ledgerRange) if err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, @@ -88,14 +98,6 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont } } - ledgerRange, err := h.dbReader.GetLedgerRange(ctx) - if err != nil { - return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, - Message: err.Error(), - } - } - // Iterate through each ledger and its transactions until limit or end range is reached. // The latest ledger acts as the end ledger range for the request. var txns []db.Transaction diff --git a/cmd/soroban-rpc/internal/methods/get_transactions_test.go b/cmd/soroban-rpc/internal/methods/get_transactions_test.go index a299ea93..186b7be9 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions_test.go @@ -35,12 +35,12 @@ func createTestLedger(sequence uint32) xdr.LedgerCloseMeta { func TestGetTransactions_DefaultLimit(t *testing.T) { mockDbReader := db.NewMockTransactionStore(NetworkPassphrase) + mockLedgerReader := db.NewMockLedgerReader(mockDbReader) for i := 1; i <= 10; i++ { meta := createTestLedger(uint32(i)) err := mockDbReader.InsertTransactions(meta) assert.NoError(t, err) } - mockLedgerReader := db.NewMockLedgerReader(mockDbReader) handler := transactionsRPCHandler{ ledgerReader: mockLedgerReader, @@ -70,12 +70,12 @@ func TestGetTransactions_DefaultLimit(t *testing.T) { func TestGetTransactions_DefaultLimitExceedsLatestLedger(t *testing.T) { mockDbReader := db.NewMockTransactionStore(NetworkPassphrase) + mockLedgerReader := db.NewMockLedgerReader(mockDbReader) for i := 1; i <= 3; i++ { meta := createTestLedger(uint32(i)) err := mockDbReader.InsertTransactions(meta) assert.NoError(t, err) } - mockLedgerReader := db.NewMockLedgerReader(mockDbReader) handler := transactionsRPCHandler{ ledgerReader: mockLedgerReader, @@ -103,153 +103,171 @@ func TestGetTransactions_DefaultLimitExceedsLatestLedger(t *testing.T) { assert.Equal(t, len(response.Transactions), 6) } -//func TestGetTransactions_CustomLimit(t *testing.T) { -// ctrl := gomock.NewController(t) -// defer ctrl.Finish() -// -// mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, 10, nil) -// -// handler := transactionsRPCHandler{ -// ledgerReader: mockLedgerReader, -// ledgerEntryReader: mockLedgerEntryReader, -// maxLimit: 100, -// defaultLimit: 10, -// networkPassphrase: NetworkPassphrase, -// } -// -// request := GetTransactionsRequest{ -// StartLedger: 1, -// Pagination: &TransactionsPaginationOptions{ -// Limit: 2, -// }, -// } -// -// response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) -// assert.NoError(t, err) -// -// // assert latest ledger details -// assert.Equal(t, response.LatestLedger, int64(10)) -// assert.Equal(t, response.LatestLedgerCloseTimestamp, int64(350)) -// -// // assert pagination -// assert.Equal(t, response.Cursor, toid.New(1, 1, 0).String()) -// -// // assert transactions result -// assert.Equal(t, len(response.Transactions), 2) -// assert.Equal(t, int(response.Transactions[0].LedgerSequence), 1) -// assert.Equal(t, int(response.Transactions[1].LedgerSequence), 1) -//} -// -//func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { -// ctrl := gomock.NewController(t) -// defer ctrl.Finish() -// -// mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, 10, nil) -// -// handler := transactionsRPCHandler{ -// ledgerReader: mockLedgerReader, -// ledgerEntryReader: mockLedgerEntryReader, -// maxLimit: 100, -// defaultLimit: 10, -// networkPassphrase: NetworkPassphrase, -// } -// -// request := GetTransactionsRequest{ -// Pagination: &TransactionsPaginationOptions{ -// Cursor: &toid.ID{ -// LedgerSequence: 1, -// TransactionOrder: 1, -// OperationOrder: 0, -// }, -// Limit: 3, -// }, -// } -// -// response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) -// assert.NoError(t, err) -// -// // assert latest ledger details -// assert.Equal(t, response.LatestLedger, int64(10)) -// assert.Equal(t, response.LatestLedgerCloseTimestamp, int64(350)) -// -// // assert pagination -// assert.Equal(t, response.Cursor, toid.New(3, 0, 0).String()) -// -// // assert transactions result -// assert.Equal(t, len(response.Transactions), 3) -// assert.Equal(t, int(response.Transactions[0].LedgerSequence), 2) -// assert.Equal(t, int(response.Transactions[1].LedgerSequence), 2) -// assert.Equal(t, int(response.Transactions[2].LedgerSequence), 3) -//} -// -//func TestGetTransactions_LedgerNotFound(t *testing.T) { -// ctrl := gomock.NewController(t) -// defer ctrl.Finish() -// -// mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, false, 10, nil) -// -// handler := transactionsRPCHandler{ -// ledgerReader: mockLedgerReader, -// ledgerEntryReader: mockLedgerEntryReader, -// maxLimit: 100, -// defaultLimit: 10, -// networkPassphrase: NetworkPassphrase, -// } -// -// request := GetTransactionsRequest{ -// StartLedger: 1, -// } -// -// response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) -// assert.Equal(t, err.Error(), "[-32602] ledger close meta not found: 10") -// assert.Nil(t, response.Transactions) -//} -// -//func TestGetTransactions_LedgerDbError(t *testing.T) { -// ctrl := gomock.NewController(t) -// defer ctrl.Finish() -// -// err := errors.New("error reading from db") -// mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, false, 10, err) -// -// handler := transactionsRPCHandler{ -// ledgerReader: mockLedgerReader, -// ledgerEntryReader: mockLedgerEntryReader, -// maxLimit: 100, -// defaultLimit: 10, -// networkPassphrase: NetworkPassphrase, -// } -// -// request := GetTransactionsRequest{ -// StartLedger: 1, -// } -// -// response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) -// assert.Equal(t, err.Error(), "[-32602] error reading from db") -// assert.Nil(t, response.Transactions) -//} -// -//func TestGetTransactions_LimitGreaterThanMaxLimit(t *testing.T) { -// ctrl := gomock.NewController(t) -// defer ctrl.Finish() -// -// mockLedgerEntryReader, mockLedgerReader := getMockReaders(ctrl, true, 10, nil) -// -// handler := transactionsRPCHandler{ -// ledgerReader: mockLedgerReader, -// ledgerEntryReader: mockLedgerEntryReader, -// maxLimit: 100, -// defaultLimit: 10, -// networkPassphrase: NetworkPassphrase, -// } -// -// request := GetTransactionsRequest{ -// StartLedger: 1, -// Pagination: &TransactionsPaginationOptions{ -// Limit: 200, -// }, -// } -// -// _, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) -// assert.Equal(t, err.Error(), "[-32602] limit must not exceed 100") -//} +func TestGetTransactions_CustomLimit(t *testing.T) { + mockDbReader := db.NewMockTransactionStore(NetworkPassphrase) + mockLedgerReader := db.NewMockLedgerReader(mockDbReader) + for i := 1; i <= 10; i++ { + meta := createTestLedger(uint32(i)) + err := mockDbReader.InsertTransactions(meta) + assert.NoError(t, err) + } + + handler := transactionsRPCHandler{ + ledgerReader: mockLedgerReader, + dbReader: mockDbReader, + maxLimit: 100, + defaultLimit: 10, + networkPassphrase: NetworkPassphrase, + } + + request := GetTransactionsRequest{ + StartLedger: 1, + Pagination: &TransactionsPaginationOptions{ + Limit: 2, + }, + } + + response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) + assert.NoError(t, err) + + // assert latest ledger details + assert.Equal(t, response.LatestLedger, uint32(10)) + assert.Equal(t, response.LatestLedgerCloseTime, int64(350)) + + // assert pagination + assert.Equal(t, response.Cursor, toid.New(1, 1, 0).String()) + + // assert transactions result + assert.Equal(t, len(response.Transactions), 2) + assert.Equal(t, response.Transactions[0].Ledger.Sequence, uint32(1)) + assert.Equal(t, response.Transactions[1].Ledger.Sequence, uint32(1)) +} + +func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { + mockDbReader := db.NewMockTransactionStore(NetworkPassphrase) + mockLedgerReader := db.NewMockLedgerReader(mockDbReader) + for i := 1; i <= 10; i++ { + meta := createTestLedger(uint32(i)) + err := mockDbReader.InsertTransactions(meta) + assert.NoError(t, err) + } + + handler := transactionsRPCHandler{ + ledgerReader: mockLedgerReader, + dbReader: mockDbReader, + maxLimit: 100, + defaultLimit: 10, + networkPassphrase: NetworkPassphrase, + } + + request := GetTransactionsRequest{ + Pagination: &TransactionsPaginationOptions{ + Cursor: &toid.ID{ + LedgerSequence: 1, + TransactionOrder: 1, + OperationOrder: 0, + }, + Limit: 3, + }, + } + + response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) + assert.NoError(t, err) + + // assert latest ledger details + assert.Equal(t, response.LatestLedger, uint32(10)) + assert.Equal(t, response.LatestLedgerCloseTime, int64(350)) + + // assert pagination + assert.Equal(t, response.Cursor, toid.New(3, 0, 0).String()) + + // assert transactions result + assert.Equal(t, len(response.Transactions), 3) + assert.Equal(t, response.Transactions[0].Ledger.Sequence, uint32(2)) + assert.Equal(t, response.Transactions[1].Ledger.Sequence, uint32(2)) + assert.Equal(t, response.Transactions[2].Ledger.Sequence, uint32(3)) +} + +func TestGetTransactions_InvalidStartLedger(t *testing.T) { + mockDbReader := db.NewMockTransactionStore(NetworkPassphrase) + mockLedgerReader := db.NewMockLedgerReader(mockDbReader) + for i := 1; i <= 3; i++ { + meta := createTestLedger(uint32(i)) + err := mockDbReader.InsertTransactions(meta) + assert.NoError(t, err) + } + + handler := transactionsRPCHandler{ + ledgerReader: mockLedgerReader, + dbReader: mockDbReader, + maxLimit: 100, + defaultLimit: 10, + networkPassphrase: NetworkPassphrase, + } + + request := GetTransactionsRequest{ + StartLedger: 4, + } + + response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) + assert.Equal(t, err.Error(), "[-32602] start ledger must be between the oldest ledger: 1 and the latest ledger: 3 for this rpc instance.") + assert.Nil(t, response.Transactions) +} + +func TestGetTransactions_LedgerNotFound(t *testing.T) { + mockDbReader := db.NewMockTransactionStore(NetworkPassphrase) + mockLedgerReader := db.NewMockLedgerReader(mockDbReader) + for i := 1; i <= 3; i++ { + // Skip creation of ledger 2 + if i == 2 { + continue + } + meta := createTestLedger(uint32(i)) + err := mockDbReader.InsertTransactions(meta) + assert.NoError(t, err) + } + + handler := transactionsRPCHandler{ + ledgerReader: mockLedgerReader, + dbReader: mockDbReader, + maxLimit: 100, + defaultLimit: 10, + networkPassphrase: NetworkPassphrase, + } + + request := GetTransactionsRequest{ + StartLedger: 1, + } + + response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) + assert.Equal(t, err.Error(), "[-32602] ledger close meta not found: 2") + assert.Nil(t, response.Transactions) +} + +func TestGetTransactions_LimitGreaterThanMaxLimit(t *testing.T) { + mockDbReader := db.NewMockTransactionStore(NetworkPassphrase) + mockLedgerReader := db.NewMockLedgerReader(mockDbReader) + for i := 1; i <= 3; i++ { + meta := createTestLedger(uint32(i)) + err := mockDbReader.InsertTransactions(meta) + assert.NoError(t, err) + } + + handler := transactionsRPCHandler{ + ledgerReader: mockLedgerReader, + dbReader: mockDbReader, + maxLimit: 100, + defaultLimit: 10, + networkPassphrase: NetworkPassphrase, + } + + request := GetTransactionsRequest{ + StartLedger: 1, + Pagination: &TransactionsPaginationOptions{ + Limit: 200, + }, + } + + _, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) + assert.Equal(t, err.Error(), "[-32602] limit must not exceed 100") +} From af41b32c1d1fe601e96d0442380ff4122223728d Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Mon, 6 May 2024 11:11:34 -0400 Subject: [PATCH 41/57] Refactor integration test --- .../internal/test/get_transactions_test.go | 56 ++++++++----------- 1 file changed, 23 insertions(+), 33 deletions(-) diff --git a/cmd/soroban-rpc/internal/test/get_transactions_test.go b/cmd/soroban-rpc/internal/test/get_transactions_test.go index 3dda9806..c73b4910 100644 --- a/cmd/soroban-rpc/internal/test/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/test/get_transactions_test.go @@ -8,6 +8,7 @@ import ( "github.com/creachadair/jrpc2" "github.com/creachadair/jrpc2/jhttp" "github.com/stellar/go/keypair" + "github.com/stellar/go/toid" "github.com/stellar/go/txnbuild" "github.com/stretchr/testify/assert" @@ -112,40 +113,29 @@ func TestGetTransactions(t *testing.T) { assert.Equal(t, result.Transactions[1].Ledger.Sequence, ledgers[1]) assert.Equal(t, result.Transactions[2].Ledger.Sequence, ledgers[2]) - // Get transactions from single ledger - //request = methods.GetTransactionsRequest{ - // StartLedger: ledgers[0], - //} - //err = client.CallResult(context.Background(), "getTransactions", request, &result) - //assert.NoError(t, err) - //assert.Equal(t, len(result.Transactions), 3) - //assert.Equal(t, result.Transactions[0].LedgerSequence, ledgers[0]) - //assert.Equal(t, result.Transactions[1].LedgerSequence, ledgers[1]) - //assert.Equal(t, result.Transactions[2].LedgerSequence, ledgers[2]) - // Get transactions with limit - //request = methods.GetTransactionsRequest{ - // StartLedger: ledgers[0], - // Pagination: &methods.TransactionsPaginationOptions{ - // Limit: 1, - // }, - //} - //err = client.CallResult(context.Background(), "getTransactions", request, &result) - //assert.NoError(t, err) - //assert.Equal(t, len(result.Transactions), 1) - //assert.Equal(t, result.Transactions[0].LedgerSequence, ledgers[0]) + request = methods.GetTransactionsRequest{ + StartLedger: ledgers[0], + Pagination: &methods.TransactionsPaginationOptions{ + Limit: 1, + }, + } + err = client.CallResult(context.Background(), "getTransactions", request, &result) + assert.NoError(t, err) + assert.Equal(t, len(result.Transactions), 1) + assert.Equal(t, result.Transactions[0].Ledger.Sequence, ledgers[0]) // Get transactions using previous result's cursor - //cursor := toid.Parse(Cursor) - //request = methods.GetTransactionsRequest{ - // Pagination: &methods.TransactionsPaginationOptions{ - // Cursor: &cursor, - // Limit: 5, - // }, - //} - //err = client.CallResult(context.Background(), "getTransactions", request, &result) - //assert.NoError(t, err) - //assert.Equal(t, len(result.Transactions), 2) - //assert.Equal(t, result.Transactions[0].LedgerSequence, ledgers[1]) - //assert.Equal(t, result.Transactions[1].LedgerSequence, ledgers[2]) + cursor := toid.Parse(Cursor) + request = methods.GetTransactionsRequest{ + Pagination: &methods.TransactionsPaginationOptions{ + Cursor: &cursor, + Limit: 5, + }, + } + err = client.CallResult(context.Background(), "getTransactions", request, &result) + assert.NoError(t, err) + assert.Equal(t, len(result.Transactions), 2) + assert.Equal(t, result.Transactions[0].Ledger.Sequence, ledgers[1]) + assert.Equal(t, result.Transactions[1].Ledger.Sequence, ledgers[2]) } From 90afd1e736a9ea8a6fec0f5ce29e29356f91ba09 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Mon, 6 May 2024 11:18:18 -0400 Subject: [PATCH 42/57] Add config vars for max requests and request duration --- cmd/soroban-rpc/internal/config/config.go | 2 ++ cmd/soroban-rpc/internal/config/options.go | 13 +++++++++++++ cmd/soroban-rpc/internal/jsonrpc.go | 4 ++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/cmd/soroban-rpc/internal/config/config.go b/cmd/soroban-rpc/internal/config/config.go index 54bdb80a..b522e424 100644 --- a/cmd/soroban-rpc/internal/config/config.go +++ b/cmd/soroban-rpc/internal/config/config.go @@ -50,6 +50,7 @@ type Config struct { RequestBacklogGetLatestLedgerQueueLimit uint RequestBacklogGetLedgerEntriesQueueLimit uint RequestBacklogGetTransactionQueueLimit uint + RequestBacklogGetTransactionsQueueLimit uint RequestBacklogSendTransactionQueueLimit uint RequestBacklogSimulateTransactionQueueLimit uint RequestExecutionWarningThreshold time.Duration @@ -61,6 +62,7 @@ type Config struct { MaxGetLatestLedgerExecutionDuration time.Duration MaxGetLedgerEntriesExecutionDuration time.Duration MaxGetTransactionExecutionDuration time.Duration + MaxGetTransactionsExecutionDuration time.Duration MaxSendTransactionExecutionDuration time.Duration MaxSimulateTransactionExecutionDuration time.Duration diff --git a/cmd/soroban-rpc/internal/config/options.go b/cmd/soroban-rpc/internal/config/options.go index 415e0309..199a2ea9 100644 --- a/cmd/soroban-rpc/internal/config/options.go +++ b/cmd/soroban-rpc/internal/config/options.go @@ -356,6 +356,13 @@ func (cfg *Config) options() ConfigOptions { DefaultValue: uint(1000), Validate: positive, }, + { + TomlKey: strutils.KebabToConstantCase("request-backlog-get-transactions-queue-limit"), + Usage: "Maximum number of outstanding GetTransactions requests", + ConfigKey: &cfg.RequestBacklogGetTransactionQueueLimit, + DefaultValue: uint(1000), + Validate: positive, + }, { TomlKey: strutils.KebabToConstantCase("request-backlog-send-transaction-queue-limit"), Usage: "Maximum number of outstanding SendTransaction requests", @@ -424,6 +431,12 @@ func (cfg *Config) options() ConfigOptions { ConfigKey: &cfg.MaxGetTransactionExecutionDuration, DefaultValue: 5 * time.Second, }, + { + TomlKey: strutils.KebabToConstantCase("max-get-transactions-execution-duration"), + Usage: "The maximum duration of time allowed for processing a getTransactions request. When that time elapses, the rpc server would return -32001 and abort the request's execution", + ConfigKey: &cfg.MaxGetTransactionExecutionDuration, + DefaultValue: 5 * time.Second, + }, { TomlKey: strutils.KebabToConstantCase("max-send-transaction-execution-duration"), Usage: "The maximum duration of time allowed for processing a sendTransaction request. When that time elapses, the rpc server would return -32001 and abort the request's execution", diff --git a/cmd/soroban-rpc/internal/jsonrpc.go b/cmd/soroban-rpc/internal/jsonrpc.go index 03e0cad7..6529e79b 100644 --- a/cmd/soroban-rpc/internal/jsonrpc.go +++ b/cmd/soroban-rpc/internal/jsonrpc.go @@ -208,8 +208,8 @@ func NewJSONRPCHandler(cfg *config.Config, params HandlerParams) Handler { methodName: "getTransactions", underlyingHandler: methods.NewGetTransactionsHandler(params.Logger, params.LedgerReader, params.TransactionReader, cfg.MaxTransactionsLimit, cfg.DefaultTransactionsLimit, cfg.NetworkPassphrase), longName: "get_transactions", - queueLimit: cfg.RequestBacklogSendTransactionQueueLimit, - requestDurationLimit: cfg.MaxSendTransactionExecutionDuration, + queueLimit: cfg.RequestBacklogGetTransactionsQueueLimit, + requestDurationLimit: cfg.MaxGetTransactionsExecutionDuration, }, { methodName: "sendTransaction", From 31c80f7ad1dd252b79e427d9b7ffd0e8b2206bb8 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Mon, 6 May 2024 11:32:32 -0400 Subject: [PATCH 43/57] Fix failing test --- cmd/soroban-rpc/internal/config/options.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/soroban-rpc/internal/config/options.go b/cmd/soroban-rpc/internal/config/options.go index 199a2ea9..20370012 100644 --- a/cmd/soroban-rpc/internal/config/options.go +++ b/cmd/soroban-rpc/internal/config/options.go @@ -359,7 +359,7 @@ func (cfg *Config) options() ConfigOptions { { TomlKey: strutils.KebabToConstantCase("request-backlog-get-transactions-queue-limit"), Usage: "Maximum number of outstanding GetTransactions requests", - ConfigKey: &cfg.RequestBacklogGetTransactionQueueLimit, + ConfigKey: &cfg.RequestBacklogGetTransactionsQueueLimit, DefaultValue: uint(1000), Validate: positive, }, @@ -434,7 +434,7 @@ func (cfg *Config) options() ConfigOptions { { TomlKey: strutils.KebabToConstantCase("max-get-transactions-execution-duration"), Usage: "The maximum duration of time allowed for processing a getTransactions request. When that time elapses, the rpc server would return -32001 and abort the request's execution", - ConfigKey: &cfg.MaxGetTransactionExecutionDuration, + ConfigKey: &cfg.MaxGetTransactionsExecutionDuration, DefaultValue: 5 * time.Second, }, { From 0a00590ae21209f090636f6eacd7372d0cca62dc Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Wed, 8 May 2024 11:50:02 -0400 Subject: [PATCH 44/57] Use transactionInfo struct instead of db.Transactions --- .../internal/methods/get_transactions.go | 51 ++++++++++++++++--- .../internal/methods/get_transactions_test.go | 10 ++-- .../internal/test/get_transactions_test.go | 12 ++--- 3 files changed, 54 insertions(+), 19 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 7f582699..0904e981 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -2,6 +2,7 @@ package methods import ( "context" + "encoding/base64" "fmt" "io" @@ -45,14 +46,37 @@ func (req GetTransactionsRequest) isValid(maxLimit uint, ledgerRange ledgerbucke return nil } +type transactionInfo struct { + // Successful indicates whether the transaction was successful or not + Successful bool `json:"status"` + // ApplicationOrder is the index of the transaction among all the transactions + // for that ledger. + ApplicationOrder int32 `json:"applicationOrder,omitempty"` + // FeeBump indicates whether the transaction is a feebump transaction + FeeBump bool `json:"feeBump,omitempty"` + // EnvelopeXdr is the TransactionEnvelope XDR value. + EnvelopeXdr string `json:"envelopeXdr,omitempty"` + // ResultXdr is the TransactionResult XDR value. + ResultXdr string `json:"resultXdr,omitempty"` + // ResultMetaXdr is the TransactionMeta XDR value. + ResultMetaXdr string `json:"resultMetaXdr,omitempty"` + // DiagnosticEventsXDR is present only if transaction was not successful. + // DiagnosticEventsXDR is a base64-encoded slice of xdr.DiagnosticEvent + DiagnosticEventsXDR []string `json:"diagnosticEventsXdr,omitempty"` + // Ledger is the sequence of the ledger which included the transaction. + Ledger uint32 `json:"ledger,omitempty"` + // LedgerCloseTime is the unix timestamp of when the transaction was included in the ledger. + LedgerCloseTime int64 `json:"createdAt,string,omitempty"` +} + // GetTransactionsResponse encapsulates the response structure for getTransactions queries. type GetTransactionsResponse struct { - Transactions []db.Transaction `json:"transactions"` - LatestLedger uint32 `json:"latestLedger"` - LatestLedgerCloseTime int64 `json:"latestLedgerCloseTimestamp"` - OldestLedger uint32 `json:"oldestLedger"` - OldestLedgerCloseTime int64 `json:"oldestLedgerCloseTimestamp"` - Cursor string `json:"cursor"` + Transactions []transactionInfo `json:"transactions"` + LatestLedger uint32 `json:"latestLedger"` + LatestLedgerCloseTime int64 `json:"latestLedgerCloseTimestamp"` + OldestLedger uint32 `json:"oldestLedger"` + OldestLedgerCloseTime int64 `json:"oldestLedgerCloseTimestamp"` + Cursor string `json:"cursor"` } type transactionsRPCHandler struct { @@ -100,7 +124,7 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont // Iterate through each ledger and its transactions until limit or end range is reached. // The latest ledger acts as the end ledger range for the request. - var txns []db.Transaction + var txns []transactionInfo var cursor *toid.ID LedgerLoop: for ledgerSeq := start.LedgerSequence; ledgerSeq <= int32(ledgerRange.LastLedger.Sequence); ledgerSeq++ { @@ -162,7 +186,18 @@ LedgerLoop: } } - txns = append(txns, tx) + txInfo := transactionInfo{ + Successful: tx.Successful, + ApplicationOrder: tx.ApplicationOrder, + FeeBump: tx.FeeBump, + ResultXdr: base64.StdEncoding.EncodeToString(tx.Result), + ResultMetaXdr: base64.StdEncoding.EncodeToString(tx.Meta), + EnvelopeXdr: base64.StdEncoding.EncodeToString(tx.Envelope), + DiagnosticEventsXDR: base64EncodeSlice(tx.Events), + Ledger: tx.Ledger.Sequence, + LedgerCloseTime: tx.Ledger.CloseTime, + } + txns = append(txns, txInfo) if len(txns) >= int(limit) { break LedgerLoop } diff --git a/cmd/soroban-rpc/internal/methods/get_transactions_test.go b/cmd/soroban-rpc/internal/methods/get_transactions_test.go index 186b7be9..9fb29764 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions_test.go @@ -139,8 +139,8 @@ func TestGetTransactions_CustomLimit(t *testing.T) { // assert transactions result assert.Equal(t, len(response.Transactions), 2) - assert.Equal(t, response.Transactions[0].Ledger.Sequence, uint32(1)) - assert.Equal(t, response.Transactions[1].Ledger.Sequence, uint32(1)) + assert.Equal(t, response.Transactions[0].Ledger, uint32(1)) + assert.Equal(t, response.Transactions[1].Ledger, uint32(1)) } func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { @@ -183,9 +183,9 @@ func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { // assert transactions result assert.Equal(t, len(response.Transactions), 3) - assert.Equal(t, response.Transactions[0].Ledger.Sequence, uint32(2)) - assert.Equal(t, response.Transactions[1].Ledger.Sequence, uint32(2)) - assert.Equal(t, response.Transactions[2].Ledger.Sequence, uint32(3)) + assert.Equal(t, response.Transactions[0].Ledger, uint32(2)) + assert.Equal(t, response.Transactions[1].Ledger, uint32(2)) + assert.Equal(t, response.Transactions[2].Ledger, uint32(3)) } func TestGetTransactions_InvalidStartLedger(t *testing.T) { diff --git a/cmd/soroban-rpc/internal/test/get_transactions_test.go b/cmd/soroban-rpc/internal/test/get_transactions_test.go index c73b4910..90ce2b8f 100644 --- a/cmd/soroban-rpc/internal/test/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/test/get_transactions_test.go @@ -109,9 +109,9 @@ func TestGetTransactions(t *testing.T) { err := client.CallResult(context.Background(), "getTransactions", request, &result) assert.NoError(t, err) assert.Equal(t, len(result.Transactions), 3) - assert.Equal(t, result.Transactions[0].Ledger.Sequence, ledgers[0]) - assert.Equal(t, result.Transactions[1].Ledger.Sequence, ledgers[1]) - assert.Equal(t, result.Transactions[2].Ledger.Sequence, ledgers[2]) + assert.Equal(t, result.Transactions[0].Ledger, ledgers[0]) + assert.Equal(t, result.Transactions[1].Ledger, ledgers[1]) + assert.Equal(t, result.Transactions[2].Ledger, ledgers[2]) // Get transactions with limit request = methods.GetTransactionsRequest{ @@ -123,7 +123,7 @@ func TestGetTransactions(t *testing.T) { err = client.CallResult(context.Background(), "getTransactions", request, &result) assert.NoError(t, err) assert.Equal(t, len(result.Transactions), 1) - assert.Equal(t, result.Transactions[0].Ledger.Sequence, ledgers[0]) + assert.Equal(t, result.Transactions[0].Ledger, ledgers[0]) // Get transactions using previous result's cursor cursor := toid.Parse(Cursor) @@ -136,6 +136,6 @@ func TestGetTransactions(t *testing.T) { err = client.CallResult(context.Background(), "getTransactions", request, &result) assert.NoError(t, err) assert.Equal(t, len(result.Transactions), 2) - assert.Equal(t, result.Transactions[0].Ledger.Sequence, ledgers[1]) - assert.Equal(t, result.Transactions[1].Ledger.Sequence, ledgers[2]) + assert.Equal(t, result.Transactions[0].Ledger, ledgers[1]) + assert.Equal(t, result.Transactions[1].Ledger, ledgers[2]) } From 0b19b1771136fa64b41fd3720632894c6f07d0b9 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Wed, 8 May 2024 12:25:12 -0400 Subject: [PATCH 45/57] Start indexing from 1 instead of 0 for toid --- cmd/soroban-rpc/internal/methods/get_transactions.go | 8 ++++---- .../internal/methods/get_transactions_test.go | 10 +++++----- cmd/soroban-rpc/internal/test/get_transactions_test.go | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 0904e981..4c4a81e3 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -108,7 +108,7 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont } // Move start to pagination cursor - start := toid.New(int32(request.StartLedger), 0, 0) + start := toid.New(int32(request.StartLedger), 1, 0) limit := h.defaultLimit if request.Pagination != nil { if request.Pagination.Cursor != nil { @@ -150,10 +150,10 @@ LedgerLoop: } // Move the reader to specific tx idx - startTxIdx := 0 + startTxIdx := 1 if ledgerSeq == start.LedgerSequence { startTxIdx = int(start.TransactionOrder) - if ierr := reader.Seek(startTxIdx); ierr != nil && ierr != io.EOF { + if ierr := reader.Seek(startTxIdx - 1); ierr != nil && ierr != io.EOF { return GetTransactionsResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, Message: err.Error(), @@ -163,7 +163,7 @@ LedgerLoop: // Decode transaction info from ledger meta txCount := ledger.CountTransactions() - for i := startTxIdx; i < txCount; i++ { + for i := startTxIdx; i <= txCount; i++ { cursor = toid.New(int32(ledger.LedgerSequence()), int32(i), 0) ingestTx, err := reader.Read() diff --git a/cmd/soroban-rpc/internal/methods/get_transactions_test.go b/cmd/soroban-rpc/internal/methods/get_transactions_test.go index 9fb29764..a3b1ed01 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions_test.go @@ -62,7 +62,7 @@ func TestGetTransactions_DefaultLimit(t *testing.T) { assert.Equal(t, response.LatestLedgerCloseTime, int64(350)) // assert pagination - assert.Equal(t, response.Cursor, toid.New(5, 1, 0).String()) + assert.Equal(t, response.Cursor, toid.New(5, 2, 0).String()) // assert transactions result assert.Equal(t, len(response.Transactions), 10) @@ -97,7 +97,7 @@ func TestGetTransactions_DefaultLimitExceedsLatestLedger(t *testing.T) { assert.Equal(t, response.LatestLedgerCloseTime, int64(175)) // assert pagination - assert.Equal(t, response.Cursor, toid.New(3, 1, 0).String()) + assert.Equal(t, response.Cursor, toid.New(3, 2, 0).String()) // assert transactions result assert.Equal(t, len(response.Transactions), 6) @@ -135,7 +135,7 @@ func TestGetTransactions_CustomLimit(t *testing.T) { assert.Equal(t, response.LatestLedgerCloseTime, int64(350)) // assert pagination - assert.Equal(t, response.Cursor, toid.New(1, 1, 0).String()) + assert.Equal(t, response.Cursor, toid.New(1, 2, 0).String()) // assert transactions result assert.Equal(t, len(response.Transactions), 2) @@ -164,7 +164,7 @@ func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { Pagination: &TransactionsPaginationOptions{ Cursor: &toid.ID{ LedgerSequence: 1, - TransactionOrder: 1, + TransactionOrder: 2, OperationOrder: 0, }, Limit: 3, @@ -179,7 +179,7 @@ func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { assert.Equal(t, response.LatestLedgerCloseTime, int64(350)) // assert pagination - assert.Equal(t, response.Cursor, toid.New(3, 0, 0).String()) + assert.Equal(t, response.Cursor, toid.New(3, 1, 0).String()) // assert transactions result assert.Equal(t, len(response.Transactions), 3) diff --git a/cmd/soroban-rpc/internal/test/get_transactions_test.go b/cmd/soroban-rpc/internal/test/get_transactions_test.go index 90ce2b8f..284045dc 100644 --- a/cmd/soroban-rpc/internal/test/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/test/get_transactions_test.go @@ -16,7 +16,7 @@ import ( ) const ( - Cursor int64 = 55834574848 + Cursor int64 = 55834578944 ) // buildTxParams constructs the parameters necessary for creating a transaction from the given account. From f85bdfbc59784b5a670909a645d7fdf6b4a85529 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Thu, 9 May 2024 11:26:22 -0400 Subject: [PATCH 46/57] Operation index from 1 --- cmd/soroban-rpc/internal/methods/get_transactions.go | 4 ++-- .../internal/methods/get_transactions_test.go | 10 +++++----- cmd/soroban-rpc/internal/test/get_transactions_test.go | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 4c4a81e3..f9c47f7d 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -108,7 +108,7 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont } // Move start to pagination cursor - start := toid.New(int32(request.StartLedger), 1, 0) + start := toid.New(int32(request.StartLedger), 1, 1) limit := h.defaultLimit if request.Pagination != nil { if request.Pagination.Cursor != nil { @@ -164,7 +164,7 @@ LedgerLoop: // Decode transaction info from ledger meta txCount := ledger.CountTransactions() for i := startTxIdx; i <= txCount; i++ { - cursor = toid.New(int32(ledger.LedgerSequence()), int32(i), 0) + cursor = toid.New(int32(ledger.LedgerSequence()), int32(i), 1) ingestTx, err := reader.Read() if err != nil { diff --git a/cmd/soroban-rpc/internal/methods/get_transactions_test.go b/cmd/soroban-rpc/internal/methods/get_transactions_test.go index a3b1ed01..e3150b61 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions_test.go @@ -62,7 +62,7 @@ func TestGetTransactions_DefaultLimit(t *testing.T) { assert.Equal(t, response.LatestLedgerCloseTime, int64(350)) // assert pagination - assert.Equal(t, response.Cursor, toid.New(5, 2, 0).String()) + assert.Equal(t, response.Cursor, toid.New(5, 2, 1).String()) // assert transactions result assert.Equal(t, len(response.Transactions), 10) @@ -97,7 +97,7 @@ func TestGetTransactions_DefaultLimitExceedsLatestLedger(t *testing.T) { assert.Equal(t, response.LatestLedgerCloseTime, int64(175)) // assert pagination - assert.Equal(t, response.Cursor, toid.New(3, 2, 0).String()) + assert.Equal(t, response.Cursor, toid.New(3, 2, 1).String()) // assert transactions result assert.Equal(t, len(response.Transactions), 6) @@ -135,7 +135,7 @@ func TestGetTransactions_CustomLimit(t *testing.T) { assert.Equal(t, response.LatestLedgerCloseTime, int64(350)) // assert pagination - assert.Equal(t, response.Cursor, toid.New(1, 2, 0).String()) + assert.Equal(t, response.Cursor, toid.New(1, 2, 1).String()) // assert transactions result assert.Equal(t, len(response.Transactions), 2) @@ -165,7 +165,7 @@ func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { Cursor: &toid.ID{ LedgerSequence: 1, TransactionOrder: 2, - OperationOrder: 0, + OperationOrder: 1, }, Limit: 3, }, @@ -179,7 +179,7 @@ func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { assert.Equal(t, response.LatestLedgerCloseTime, int64(350)) // assert pagination - assert.Equal(t, response.Cursor, toid.New(3, 1, 0).String()) + assert.Equal(t, response.Cursor, toid.New(3, 1, 1).String()) // assert transactions result assert.Equal(t, len(response.Transactions), 3) diff --git a/cmd/soroban-rpc/internal/test/get_transactions_test.go b/cmd/soroban-rpc/internal/test/get_transactions_test.go index 284045dc..c4b77911 100644 --- a/cmd/soroban-rpc/internal/test/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/test/get_transactions_test.go @@ -16,7 +16,7 @@ import ( ) const ( - Cursor int64 = 55834578944 + Cursor int64 = 55834578945 ) // buildTxParams constructs the parameters necessary for creating a transaction from the given account. From 444234823af762691e5660713aede728716a8684 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Thu, 9 May 2024 11:32:39 -0400 Subject: [PATCH 47/57] Add lines to make sure structs implement interfaces --- cmd/soroban-rpc/internal/db/mocks.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/soroban-rpc/internal/db/mocks.go b/cmd/soroban-rpc/internal/db/mocks.go index 19c8c142..d2dfba4f 100644 --- a/cmd/soroban-rpc/internal/db/mocks.go +++ b/cmd/soroban-rpc/internal/db/mocks.go @@ -104,3 +104,7 @@ func (m *mockLedgerReader) GetLedger(ctx context.Context, sequence uint32) (xdr. func (m *mockLedgerReader) StreamAllLedgers(ctx context.Context, f StreamLedgerFn) error { return nil } + +var _ TransactionReader = &mockTransactionHandler{} +var _ TransactionWriter = &mockTransactionHandler{} +var _ LedgerReader = &mockLedgerReader{} From 2d660841df55a3e5d5b569c07948ea66aad1481d Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Thu, 9 May 2024 11:37:22 -0400 Subject: [PATCH 48/57] Remove omitempty --- .../internal/methods/get_transactions.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index f9c47f7d..54f61721 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -51,22 +51,22 @@ type transactionInfo struct { Successful bool `json:"status"` // ApplicationOrder is the index of the transaction among all the transactions // for that ledger. - ApplicationOrder int32 `json:"applicationOrder,omitempty"` + ApplicationOrder int32 `json:"applicationOrder"` // FeeBump indicates whether the transaction is a feebump transaction - FeeBump bool `json:"feeBump,omitempty"` + FeeBump bool `json:"feeBump"` // EnvelopeXdr is the TransactionEnvelope XDR value. - EnvelopeXdr string `json:"envelopeXdr,omitempty"` + EnvelopeXdr string `json:"envelopeXdr"` // ResultXdr is the TransactionResult XDR value. - ResultXdr string `json:"resultXdr,omitempty"` + ResultXdr string `json:"resultXdr"` // ResultMetaXdr is the TransactionMeta XDR value. - ResultMetaXdr string `json:"resultMetaXdr,omitempty"` + ResultMetaXdr string `json:"resultMetaXdr"` // DiagnosticEventsXDR is present only if transaction was not successful. // DiagnosticEventsXDR is a base64-encoded slice of xdr.DiagnosticEvent DiagnosticEventsXDR []string `json:"diagnosticEventsXdr,omitempty"` // Ledger is the sequence of the ledger which included the transaction. - Ledger uint32 `json:"ledger,omitempty"` + Ledger uint32 `json:"ledger"` // LedgerCloseTime is the unix timestamp of when the transaction was included in the ledger. - LedgerCloseTime int64 `json:"createdAt,string,omitempty"` + LedgerCloseTime int64 `json:"createdAt"` } // GetTransactionsResponse encapsulates the response structure for getTransactions queries. From f08dc00b90e54837ccd69ae02b8661d1cd75e81d Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Thu, 9 May 2024 16:55:51 -0400 Subject: [PATCH 49/57] rename test func --- cmd/soroban-rpc/internal/test/get_transactions_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/soroban-rpc/internal/test/get_transactions_test.go b/cmd/soroban-rpc/internal/test/get_transactions_test.go index c4b77911..1dc7420e 100644 --- a/cmd/soroban-rpc/internal/test/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/test/get_transactions_test.go @@ -19,12 +19,12 @@ const ( Cursor int64 = 55834578945 ) -// buildTxParams constructs the parameters necessary for creating a transaction from the given account. +// buildSetOptionsTxParams constructs the parameters necessary for creating a transaction from the given account. // // account - the source account from which the transaction will originate. This account provides the starting sequence number. // // Returns a fully populated TransactionParams structure. -func buildTxParams(account txnbuild.SimpleAccount) txnbuild.TransactionParams { +func buildSetOptionsTxParams(account txnbuild.SimpleAccount) txnbuild.TransactionParams { params := txnbuild.TransactionParams{ SourceAccount: &account, IncrementSequenceNum: true, @@ -76,7 +76,7 @@ func sendTransactions(t *testing.T, client *jrpc2.Client) []uint32 { var hashes []string for i := 0; i <= 2; i++ { account := txnbuild.NewSimpleAccount(address, int64(i)) - tx, err := txnbuild.NewTransaction(buildTxParams(account)) + tx, err := txnbuild.NewTransaction(buildSetOptionsTxParams(account)) assert.NoError(t, err) hash, err := sendTransaction(t, client, kp, tx) From bc6cbba18dcd515fd9f07658a0fe842b127a4f59 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Fri, 10 May 2024 09:11:32 -0400 Subject: [PATCH 50/57] make txInfo struct public and convert string cursor to int --- cmd/soroban-rpc/internal/methods/get_transactions.go | 8 ++++---- cmd/soroban-rpc/internal/test/get_transactions_test.go | 9 ++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 54f61721..57a4e890 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -46,7 +46,7 @@ func (req GetTransactionsRequest) isValid(maxLimit uint, ledgerRange ledgerbucke return nil } -type transactionInfo struct { +type TransactionInfo struct { // Successful indicates whether the transaction was successful or not Successful bool `json:"status"` // ApplicationOrder is the index of the transaction among all the transactions @@ -71,7 +71,7 @@ type transactionInfo struct { // GetTransactionsResponse encapsulates the response structure for getTransactions queries. type GetTransactionsResponse struct { - Transactions []transactionInfo `json:"transactions"` + Transactions []TransactionInfo `json:"transactions"` LatestLedger uint32 `json:"latestLedger"` LatestLedgerCloseTime int64 `json:"latestLedgerCloseTimestamp"` OldestLedger uint32 `json:"oldestLedger"` @@ -124,7 +124,7 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont // Iterate through each ledger and its transactions until limit or end range is reached. // The latest ledger acts as the end ledger range for the request. - var txns []transactionInfo + var txns []TransactionInfo var cursor *toid.ID LedgerLoop: for ledgerSeq := start.LedgerSequence; ledgerSeq <= int32(ledgerRange.LastLedger.Sequence); ledgerSeq++ { @@ -186,7 +186,7 @@ LedgerLoop: } } - txInfo := transactionInfo{ + txInfo := TransactionInfo{ Successful: tx.Successful, ApplicationOrder: tx.ApplicationOrder, FeeBump: tx.FeeBump, diff --git a/cmd/soroban-rpc/internal/test/get_transactions_test.go b/cmd/soroban-rpc/internal/test/get_transactions_test.go index 1dc7420e..f3111ef8 100644 --- a/cmd/soroban-rpc/internal/test/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/test/get_transactions_test.go @@ -2,6 +2,7 @@ package test import ( "context" + "strconv" "testing" "time" @@ -15,10 +16,6 @@ import ( "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/methods" ) -const ( - Cursor int64 = 55834578945 -) - // buildSetOptionsTxParams constructs the parameters necessary for creating a transaction from the given account. // // account - the source account from which the transaction will originate. This account provides the starting sequence number. @@ -126,7 +123,9 @@ func TestGetTransactions(t *testing.T) { assert.Equal(t, result.Transactions[0].Ledger, ledgers[0]) // Get transactions using previous result's cursor - cursor := toid.Parse(Cursor) + c, err := strconv.ParseInt(result.Cursor, 10, 64) + assert.NoError(t, err) + cursor := toid.Parse(c) request = methods.GetTransactionsRequest{ Pagination: &methods.TransactionsPaginationOptions{ Cursor: &cursor, From 68e45d56d50915832d8248529903ff2300b1bd75 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Fri, 10 May 2024 09:16:18 -0400 Subject: [PATCH 51/57] Use sendSuccessfulTransaction helper func --- .../internal/test/get_transactions_test.go | 40 ++----------------- 1 file changed, 3 insertions(+), 37 deletions(-) diff --git a/cmd/soroban-rpc/internal/test/get_transactions_test.go b/cmd/soroban-rpc/internal/test/get_transactions_test.go index f3111ef8..aeb88d80 100644 --- a/cmd/soroban-rpc/internal/test/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/test/get_transactions_test.go @@ -4,7 +4,6 @@ import ( "context" "strconv" "testing" - "time" "github.com/creachadair/jrpc2" "github.com/creachadair/jrpc2/jhttp" @@ -34,30 +33,6 @@ func buildSetOptionsTxParams(account txnbuild.SimpleAccount) txnbuild.Transactio return params } -// sendTransaction submits a single transaction to the Stellar network via the given JSON-RPC client and returns -// the transaction hash. -// -// t - the testing framework handle for assertions. -// client - the JSON-RPC client used to send the transaction. -// kp - the Stellar keypair used to sign the transaction. -// transaction - the Stellar transaction to be sent. -// -// Returns the expected transaction hash as a hex string and any error encountered during the transaction submission. -func sendTransaction(t *testing.T, client *jrpc2.Client, kp *keypair.Full, transaction *txnbuild.Transaction) (string, error) { - tx, err := transaction.Sign(StandaloneNetworkPassphrase, kp) - assert.NoError(t, err) - b64, err := tx.Base64() - assert.NoError(t, err) - - request := methods.SendTransactionRequest{Transaction: b64} - var result methods.SendTransactionResponse - - expectedHashHex, err := tx.HashHex(StandaloneNetworkPassphrase) - assert.NoError(t, err) - - return expectedHashHex, client.CallResult(context.Background(), "sendTransaction", request, &result) -} - // sendTransactions sends multiple transactions for testing purposes. // It sends a total of three transactions, each from a new account sequence, and gathers the ledger // numbers where these transactions were recorded. @@ -70,23 +45,14 @@ func sendTransactions(t *testing.T, client *jrpc2.Client) []uint32 { kp := keypair.Root(StandaloneNetworkPassphrase) address := kp.Address() - var hashes []string + var ledgers []uint32 for i := 0; i <= 2; i++ { account := txnbuild.NewSimpleAccount(address, int64(i)) tx, err := txnbuild.NewTransaction(buildSetOptionsTxParams(account)) assert.NoError(t, err) - hash, err := sendTransaction(t, client, kp, tx) - assert.NoError(t, err) - hashes = append(hashes, hash) - time.Sleep(1 * time.Second) - } - - var ledgers []uint32 - for _, hash := range hashes { - response := getTransaction(t, client, hash) - assert.NotNil(t, response) - ledgers = append(ledgers, response.Ledger) + txResponse := sendSuccessfulTransaction(t, client, kp, tx) + ledgers = append(ledgers, txResponse.Ledger) } return ledgers } From 21da9055dad09a21dc4522760f0b7702eb3833ef Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Fri, 10 May 2024 13:18:06 -0400 Subject: [PATCH 52/57] Convert cursor to string in request --- .../internal/methods/get_transactions.go | 19 ++++++++++++++----- .../internal/methods/get_transactions_test.go | 8 ++------ .../internal/test/get_transactions_test.go | 7 +------ 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 57a4e890..226519de 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -5,6 +5,7 @@ import ( "encoding/base64" "fmt" "io" + "strconv" "github.com/creachadair/jrpc2" "github.com/creachadair/jrpc2/handler" @@ -19,8 +20,8 @@ import ( // TransactionsPaginationOptions defines the available options for paginating through transactions. type TransactionsPaginationOptions struct { - Cursor *toid.ID `json:"cursor,omitempty"` - Limit uint `json:"limit,omitempty"` + Cursor string `json:"cursor,omitempty"` + Limit uint `json:"limit,omitempty"` } // GetTransactionsRequest represents the request parameters for fetching transactions within a range of ledgers. @@ -31,7 +32,7 @@ type GetTransactionsRequest struct { // isValid checks the validity of the request parameters. func (req GetTransactionsRequest) isValid(maxLimit uint, ledgerRange ledgerbucketwindow.LedgerRange) error { - if req.Pagination != nil && req.Pagination.Cursor != nil { + if req.Pagination != nil && req.Pagination.Cursor != "" { if req.StartLedger != 0 { return errors.New("startLedger and cursor cannot both be set") } @@ -111,8 +112,16 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont start := toid.New(int32(request.StartLedger), 1, 1) limit := h.defaultLimit if request.Pagination != nil { - if request.Pagination.Cursor != nil { - start = request.Pagination.Cursor + if request.Pagination.Cursor != "" { + cursorInt, err := strconv.ParseInt(request.Pagination.Cursor, 10, 64) + if err != nil { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: err.Error(), + } + } + + *start = toid.Parse(cursorInt) // increment tx index because, when paginating, // we start with the item right after the cursor start.TransactionOrder++ diff --git a/cmd/soroban-rpc/internal/methods/get_transactions_test.go b/cmd/soroban-rpc/internal/methods/get_transactions_test.go index e3150b61..2bedd75e 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions_test.go @@ -162,12 +162,8 @@ func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { request := GetTransactionsRequest{ Pagination: &TransactionsPaginationOptions{ - Cursor: &toid.ID{ - LedgerSequence: 1, - TransactionOrder: 2, - OperationOrder: 1, - }, - Limit: 3, + Cursor: toid.New(1, 2, 1).String(), + Limit: 3, }, } diff --git a/cmd/soroban-rpc/internal/test/get_transactions_test.go b/cmd/soroban-rpc/internal/test/get_transactions_test.go index aeb88d80..f3da92dd 100644 --- a/cmd/soroban-rpc/internal/test/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/test/get_transactions_test.go @@ -2,13 +2,11 @@ package test import ( "context" - "strconv" "testing" "github.com/creachadair/jrpc2" "github.com/creachadair/jrpc2/jhttp" "github.com/stellar/go/keypair" - "github.com/stellar/go/toid" "github.com/stellar/go/txnbuild" "github.com/stretchr/testify/assert" @@ -89,12 +87,9 @@ func TestGetTransactions(t *testing.T) { assert.Equal(t, result.Transactions[0].Ledger, ledgers[0]) // Get transactions using previous result's cursor - c, err := strconv.ParseInt(result.Cursor, 10, 64) - assert.NoError(t, err) - cursor := toid.Parse(c) request = methods.GetTransactionsRequest{ Pagination: &methods.TransactionsPaginationOptions{ - Cursor: &cursor, + Cursor: result.Cursor, Limit: 5, }, } From 7e1a471c6501e8d486393a8ec6783b4d28ddb928 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Fri, 10 May 2024 15:36:47 -0400 Subject: [PATCH 53/57] Change jrpc response codes --- .../internal/methods/get_transactions.go | 14 ++-- .../internal/methods/get_transactions_test.go | 81 +++++++++++++------ 2 files changed, 64 insertions(+), 31 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 226519de..8f2b4596 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -95,7 +95,7 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont ledgerRange, err := h.dbReader.GetLedgerRange(ctx) if err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, + Code: jrpc2.InternalError, Message: err.Error(), } } @@ -103,7 +103,7 @@ func (h transactionsRPCHandler) getTransactionsByLedgerSequence(ctx context.Cont err = request.isValid(h.maxLimit, ledgerRange) if err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, + Code: jrpc2.InvalidRequest, Message: err.Error(), } } @@ -144,7 +144,7 @@ LedgerLoop: err = errors.Errorf("ledger close meta not found: %d", ledgerSeq) } return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, + Code: jrpc2.InternalError, Message: err.Error(), } } @@ -153,7 +153,7 @@ LedgerLoop: reader, err := ingest.NewLedgerTransactionReaderFromLedgerCloseMeta(h.networkPassphrase, ledger) if err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, + Code: jrpc2.InternalError, Message: err.Error(), } } @@ -164,7 +164,7 @@ LedgerLoop: startTxIdx = int(start.TransactionOrder) if ierr := reader.Seek(startTxIdx - 1); ierr != nil && ierr != io.EOF { return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, + Code: jrpc2.InternalError, Message: err.Error(), } } @@ -182,7 +182,7 @@ LedgerLoop: break } return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, + Code: jrpc2.InternalError, Message: err.Error(), } } @@ -190,7 +190,7 @@ LedgerLoop: tx, err := db.ParseTransaction(ledger, ingestTx) if err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, + Code: jrpc2.InternalError, Message: err.Error(), } } diff --git a/cmd/soroban-rpc/internal/methods/get_transactions_test.go b/cmd/soroban-rpc/internal/methods/get_transactions_test.go index 2bedd75e..27543fce 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions_test.go @@ -4,6 +4,8 @@ import ( "context" "testing" + "github.com/creachadair/jrpc2" + "github.com/stellar/go/support/errors" "github.com/stellar/go/toid" "github.com/stellar/go/xdr" "github.com/stretchr/testify/assert" @@ -58,14 +60,14 @@ func TestGetTransactions_DefaultLimit(t *testing.T) { assert.NoError(t, err) // assert latest ledger details - assert.Equal(t, response.LatestLedger, uint32(10)) - assert.Equal(t, response.LatestLedgerCloseTime, int64(350)) + assert.Equal(t, uint32(10), response.LatestLedger) + assert.Equal(t, int64(350), response.LatestLedgerCloseTime) // assert pagination - assert.Equal(t, response.Cursor, toid.New(5, 2, 1).String()) + assert.Equal(t, toid.New(5, 2, 1).String(), response.Cursor) // assert transactions result - assert.Equal(t, len(response.Transactions), 10) + assert.Equal(t, 10, len(response.Transactions)) } func TestGetTransactions_DefaultLimitExceedsLatestLedger(t *testing.T) { @@ -93,14 +95,14 @@ func TestGetTransactions_DefaultLimitExceedsLatestLedger(t *testing.T) { assert.NoError(t, err) // assert latest ledger details - assert.Equal(t, response.LatestLedger, uint32(3)) - assert.Equal(t, response.LatestLedgerCloseTime, int64(175)) + assert.Equal(t, uint32(3), response.LatestLedger) + assert.Equal(t, int64(175), response.LatestLedgerCloseTime) // assert pagination - assert.Equal(t, response.Cursor, toid.New(3, 2, 1).String()) + assert.Equal(t, toid.New(3, 2, 1).String(), response.Cursor) // assert transactions result - assert.Equal(t, len(response.Transactions), 6) + assert.Equal(t, 6, len(response.Transactions)) } func TestGetTransactions_CustomLimit(t *testing.T) { @@ -131,16 +133,16 @@ func TestGetTransactions_CustomLimit(t *testing.T) { assert.NoError(t, err) // assert latest ledger details - assert.Equal(t, response.LatestLedger, uint32(10)) - assert.Equal(t, response.LatestLedgerCloseTime, int64(350)) + assert.Equal(t, uint32(10), response.LatestLedger) + assert.Equal(t, int64(350), response.LatestLedgerCloseTime) // assert pagination - assert.Equal(t, response.Cursor, toid.New(1, 2, 1).String()) + assert.Equal(t, toid.New(1, 2, 1).String(), response.Cursor) // assert transactions result - assert.Equal(t, len(response.Transactions), 2) - assert.Equal(t, response.Transactions[0].Ledger, uint32(1)) - assert.Equal(t, response.Transactions[1].Ledger, uint32(1)) + assert.Equal(t, 2, len(response.Transactions)) + assert.Equal(t, uint32(1), response.Transactions[0].Ledger) + assert.Equal(t, uint32(1), response.Transactions[1].Ledger) } func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { @@ -171,17 +173,17 @@ func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { assert.NoError(t, err) // assert latest ledger details - assert.Equal(t, response.LatestLedger, uint32(10)) - assert.Equal(t, response.LatestLedgerCloseTime, int64(350)) + assert.Equal(t, uint32(10), response.LatestLedger) + assert.Equal(t, int64(350), response.LatestLedgerCloseTime) // assert pagination - assert.Equal(t, response.Cursor, toid.New(3, 1, 1).String()) + assert.Equal(t, toid.New(3, 1, 1).String(), response.Cursor) // assert transactions result - assert.Equal(t, len(response.Transactions), 3) - assert.Equal(t, response.Transactions[0].Ledger, uint32(2)) - assert.Equal(t, response.Transactions[1].Ledger, uint32(2)) - assert.Equal(t, response.Transactions[2].Ledger, uint32(3)) + assert.Equal(t, 3, len(response.Transactions)) + assert.Equal(t, uint32(2), response.Transactions[0].Ledger) + assert.Equal(t, uint32(2), response.Transactions[1].Ledger) + assert.Equal(t, uint32(3), response.Transactions[2].Ledger) } func TestGetTransactions_InvalidStartLedger(t *testing.T) { @@ -206,7 +208,8 @@ func TestGetTransactions_InvalidStartLedger(t *testing.T) { } response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) - assert.Equal(t, err.Error(), "[-32602] start ledger must be between the oldest ledger: 1 and the latest ledger: 3 for this rpc instance.") + expectedErr := errors.Errorf("[%d] start ledger must be between the oldest ledger: 1 and the latest ledger: 3 for this rpc instance.", jrpc2.InvalidRequest) + assert.Equal(t, expectedErr.Error(), err.Error()) assert.Nil(t, response.Transactions) } @@ -236,7 +239,8 @@ func TestGetTransactions_LedgerNotFound(t *testing.T) { } response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) - assert.Equal(t, err.Error(), "[-32602] ledger close meta not found: 2") + expectedErr := errors.Errorf("[%d] ledger close meta not found: 2", jrpc2.InternalError) + assert.Equal(t, expectedErr.Error(), err.Error()) assert.Nil(t, response.Transactions) } @@ -265,5 +269,34 @@ func TestGetTransactions_LimitGreaterThanMaxLimit(t *testing.T) { } _, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) - assert.Equal(t, err.Error(), "[-32602] limit must not exceed 100") + expectedErr := errors.Errorf("[%d] limit must not exceed 100", jrpc2.InvalidRequest) + assert.Equal(t, expectedErr.Error(), err.Error()) +} + +func TestGetTransactions_InvalidCursorString(t *testing.T) { + mockDbReader := db.NewMockTransactionStore(NetworkPassphrase) + mockLedgerReader := db.NewMockLedgerReader(mockDbReader) + for i := 1; i <= 3; i++ { + meta := createTestLedger(uint32(i)) + err := mockDbReader.InsertTransactions(meta) + assert.NoError(t, err) + } + + handler := transactionsRPCHandler{ + ledgerReader: mockLedgerReader, + dbReader: mockDbReader, + maxLimit: 100, + defaultLimit: 10, + networkPassphrase: NetworkPassphrase, + } + + request := GetTransactionsRequest{ + Pagination: &TransactionsPaginationOptions{ + Cursor: "abc", + }, + } + + _, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) + expectedErr := errors.Errorf("[%d] strconv.ParseInt: parsing \"abc\": invalid syntax", jrpc2.InvalidParams) + assert.Equal(t, expectedErr.Error(), err.Error()) } From c63f8e16b8ef28902669255f88eefe680edcdebb Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Mon, 13 May 2024 10:15:28 -0400 Subject: [PATCH 54/57] Change ledger close meta code to invalid-params --- cmd/soroban-rpc/internal/methods/get_transactions.go | 4 +++- cmd/soroban-rpc/internal/methods/get_transactions_test.go | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 8f2b4596..0f83eb0f 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -140,11 +140,13 @@ LedgerLoop: // Get ledger close meta from db ledger, found, err := h.ledgerReader.GetLedger(ctx, uint32(ledgerSeq)) if (err != nil) || (!found) { + code := jrpc2.InternalError if err == nil { err = errors.Errorf("ledger close meta not found: %d", ledgerSeq) + code = jrpc2.InvalidParams } return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InternalError, + Code: code, Message: err.Error(), } } diff --git a/cmd/soroban-rpc/internal/methods/get_transactions_test.go b/cmd/soroban-rpc/internal/methods/get_transactions_test.go index 27543fce..f6f7fea2 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions_test.go @@ -239,7 +239,7 @@ func TestGetTransactions_LedgerNotFound(t *testing.T) { } response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) - expectedErr := errors.Errorf("[%d] ledger close meta not found: 2", jrpc2.InternalError) + expectedErr := errors.Errorf("[%d] ledger close meta not found: 2", jrpc2.InvalidParams) assert.Equal(t, expectedErr.Error(), err.Error()) assert.Nil(t, response.Transactions) } From a6a77b9f560be2a3f745f926da1e32491c64acea Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Mon, 13 May 2024 10:23:08 -0400 Subject: [PATCH 55/57] Revert back to InvalidParams error for reader.Read() --- cmd/soroban-rpc/internal/methods/get_transactions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 0f83eb0f..b26a98ac 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -184,7 +184,7 @@ LedgerLoop: break } return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InternalError, + Code: jrpc2.InvalidParams, Message: err.Error(), } } From 7509c6e8b323bb96c56f83a0d44cc16494c59349 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Mon, 13 May 2024 11:41:46 -0400 Subject: [PATCH 56/57] Refactor if-else statement --- cmd/soroban-rpc/internal/methods/get_transactions.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index b26a98ac..2792db40 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -139,14 +139,14 @@ LedgerLoop: for ledgerSeq := start.LedgerSequence; ledgerSeq <= int32(ledgerRange.LastLedger.Sequence); ledgerSeq++ { // Get ledger close meta from db ledger, found, err := h.ledgerReader.GetLedger(ctx, uint32(ledgerSeq)) - if (err != nil) || (!found) { - code := jrpc2.InternalError - if err == nil { - err = errors.Errorf("ledger close meta not found: %d", ledgerSeq) - code = jrpc2.InvalidParams + if !found { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: errors.Errorf("ledger close meta not found: %d", ledgerSeq).Error(), } + } else if err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ - Code: code, + Code: jrpc2.InternalError, Message: err.Error(), } } From d4f9b54bd6f86b7ccfbcadc8e616dacd1ca75b1a Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Mon, 13 May 2024 12:22:48 -0400 Subject: [PATCH 57/57] Refactor if-else statement - 2 --- cmd/soroban-rpc/internal/methods/get_transactions.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index 2792db40..f8c38dd8 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -139,16 +139,16 @@ LedgerLoop: for ledgerSeq := start.LedgerSequence; ledgerSeq <= int32(ledgerRange.LastLedger.Sequence); ledgerSeq++ { // Get ledger close meta from db ledger, found, err := h.ledgerReader.GetLedger(ctx, uint32(ledgerSeq)) - if !found { - return GetTransactionsResponse{}, &jrpc2.Error{ - Code: jrpc2.InvalidParams, - Message: errors.Errorf("ledger close meta not found: %d", ledgerSeq).Error(), - } - } else if err != nil { + if err != nil { return GetTransactionsResponse{}, &jrpc2.Error{ Code: jrpc2.InternalError, Message: err.Error(), } + } else if !found { + return GetTransactionsResponse{}, &jrpc2.Error{ + Code: jrpc2.InvalidParams, + Message: errors.Errorf("ledger close meta not found: %d", ledgerSeq).Error(), + } } // Initialise tx reader.