From 4d2ad95b3686c09918f24473ecc9bfa90dcb6d7b Mon Sep 17 00:00:00 2001 From: Artem Date: Sat, 20 Dec 2025 16:02:27 +0300 Subject: [PATCH 1/3] Optimization: indexing --- internal/storage/postgres/tx.go | 25 +++++++++++++++++++------ internal/storage/postgres/tx_test.go | 22 ++++++++++++++++++++++ pkg/indexer/storage/storage.go | 2 +- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/internal/storage/postgres/tx.go b/internal/storage/postgres/tx.go index 65d71f1b..beda89d6 100644 --- a/internal/storage/postgres/tx.go +++ b/internal/storage/postgres/tx.go @@ -53,15 +53,28 @@ func (tx *Tx) setSigners(ctx context.Context, txs []storage.Tx) error { return err } + matchSignersWithTx(txs, signers) + return nil +} + +func matchSignersWithTx(txs []storage.Tx, signers []storage.Signer) { + signerMap := make(map[uint64][]storage.Address, len(txs)) + for i := range signers { - for j := range txs { - if txs[j].Id == signers[i].TxId && signers[i].Address != nil { - txs[j].Signers = append(txs[j].Signers, *signers[i].Address) - break - } + if signers[i].Address == nil { + continue + } + signerMap[signers[i].TxId] = append( + signerMap[signers[i].TxId], + *signers[i].Address, + ) + } + + for i := range txs { + if addrs, ok := signerMap[txs[i].Id]; ok { + txs[i].Signers = addrs } } - return nil } func (tx *Tx) ByHash(ctx context.Context, hash []byte) (transaction storage.Tx, err error) { diff --git a/internal/storage/postgres/tx_test.go b/internal/storage/postgres/tx_test.go index a912fdf4..d9574956 100644 --- a/internal/storage/postgres/tx_test.go +++ b/internal/storage/postgres/tx_test.go @@ -6,6 +6,8 @@ package postgres import ( "context" "encoding/hex" + "fmt" + "testing" "time" "github.com/celenium-io/celestia-indexer/internal/storage" @@ -341,3 +343,23 @@ func (s *StorageTestSuite) TestTxGas() { s.Require().EqualValues("80410", tx1.Fee.String()) s.Require().EqualValues("1", tx1.GasPrice.String()) } + +func BenchmarkSetSigners(b *testing.B) { + txs := make([]storage.Tx, 100) + signers := make([]storage.Signer, 1000) + + for i := 0; i < 100; i++ { + txs[i].Id = uint64(i) + for j := 0; j < 10; j++ { + idx := i*10 + j + signers[idx].TxId = uint64(i) + addr := storage.Address{Address: fmt.Sprintf("addr_%d", idx)} + signers[idx].Address = &addr + } + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + matchSignersWithTx(txs, signers) + } +} diff --git a/pkg/indexer/storage/storage.go b/pkg/indexer/storage/storage.go index 485de5ee..82b3395b 100644 --- a/pkg/indexer/storage/storage.go +++ b/pkg/indexer/storage/storage.go @@ -317,7 +317,7 @@ func (module *Module) processBlockInTransaction(ctx context.Context, tx storage. if err := tx.SaveEvents(ctx, events...); err != nil { return state, err } - events = make([]storage.Event, 0, 10000) + events = events[:0] } } if len(events) > 0 { From 97143efe9db788fb4344d7b519ed13d8c804a3fe Mon Sep 17 00:00:00 2001 From: Artem Date: Sat, 20 Dec 2025 16:48:11 +0300 Subject: [PATCH 2/3] Optimization: query transactions for address --- internal/storage/postgres/tx.go | 5 +++++ internal/storage/postgres/tx_test.go | 11 +++++++++++ internal/storage/tx.go | 9 +++++++++ 3 files changed, 25 insertions(+) diff --git a/internal/storage/postgres/tx.go b/internal/storage/postgres/tx.go index beda89d6..cf44a039 100644 --- a/internal/storage/postgres/tx.go +++ b/internal/storage/postgres/tx.go @@ -137,6 +137,11 @@ func (tx *Tx) ByAddress(ctx context.Context, addressId uint64, fltrs storage.TxF Model(&relations). Where("address_id = ?", addressId) + if fltrs.IsEmpty() { + signersQuery = limitScope(signersQuery, fltrs.Limit) + signersQuery = signersQuery.Offset(fltrs.Offset) + } + signersQuery = sortScope(signersQuery, "tx_id", fltrs.Sort) query := tx.DB().NewSelect(). diff --git a/internal/storage/postgres/tx_test.go b/internal/storage/postgres/tx_test.go index d9574956..6d94badd 100644 --- a/internal/storage/postgres/tx_test.go +++ b/internal/storage/postgres/tx_test.go @@ -320,6 +320,17 @@ func (s *StorageTestSuite) TestTxByAddressAndTime() { s.Require().Len(txs, 2) } +func (s *StorageTestSuite) TestTxByAddress() { + ctx, ctxCancel := context.WithTimeout(context.Background(), 5*time.Second) + defer ctxCancel() + + txs, err := s.storage.Tx.ByAddress(ctx, 1, storage.TxFilter{ + Limit: 10, + }) + s.Require().NoError(err) + s.Require().Len(txs, 3) +} + func (s *StorageTestSuite) TestTxGas() { ctx, ctxCancel := context.WithTimeout(context.Background(), 5*time.Second) defer ctxCancel() diff --git a/internal/storage/tx.go b/internal/storage/tx.go index 77045ec0..86e4b910 100644 --- a/internal/storage/tx.go +++ b/internal/storage/tx.go @@ -54,6 +54,15 @@ type TxFilter struct { WithMessages bool } +func (filter *TxFilter) IsEmpty() bool { + return len(filter.Status) == 0 && + filter.MessageTypes.Empty() && + filter.ExcludedMessageTypes.Empty() && + filter.Height == nil && + filter.TimeFrom.IsZero() && + filter.TimeTo.IsZero() +} + // Tx - type Tx struct { bun.BaseModel `bun:"tx" comment:"Table with celestia transactions."` From 2763dfe3f38f9ffc4c532ede10369eead348eeca Mon Sep 17 00:00:00 2001 From: Artem Date: Sat, 20 Dec 2025 17:03:07 +0300 Subject: [PATCH 3/3] Add index to hl_gas_payment --- internal/storage/postgres/index.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/internal/storage/postgres/index.go b/internal/storage/postgres/index.go index 04395a45..2f6583e8 100644 --- a/internal/storage/postgres/index.go +++ b/internal/storage/postgres/index.go @@ -771,6 +771,34 @@ func createIndices(ctx context.Context, conn *database.Bun) error { return err } + // Hyperlane Gas Payment + if _, err := tx.NewCreateIndex(). + IfNotExists(). + Model((*storage.HLGasPayment)(nil)). + Index("hl_gas_payment_height_idx"). + Column("height"). + Using("BRIN"). + Exec(ctx); err != nil { + return err + } + if _, err := tx.NewCreateIndex(). + IfNotExists(). + Model((*storage.HLGasPayment)(nil)). + Index("hl_gas_payment_transfer_id_idx"). + Column("transfer_id"). + Exec(ctx); err != nil { + return err + } + if _, err := tx.NewCreateIndex(). + IfNotExists(). + Model((*storage.HLGasPayment)(nil)). + Index("hl_gas_payment_igp_id_idx"). + Column("igp_id"). + Where("igp_id is not null"). + Exec(ctx); err != nil { + return err + } + // Hyperlane Mailbox if _, err := tx.NewCreateIndex(). IfNotExists().