From 1cf6da70e5b8e37af4269a406009c986104f61fd Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Mon, 5 Aug 2024 17:45:55 -0500 Subject: [PATCH 01/18] investigate, optimize and test FindTransactionsConfirmedInBlockRange query change --- core/chains/evm/txmgr/evm_tx_store.go | 49 +++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index e83a83907e4..c6a785ae189 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -665,10 +665,11 @@ func (o *evmTxStore) loadEthTxAttemptsReceipts(ctx context.Context, etx *Tx) (er return o.loadEthTxesAttemptsReceipts(ctx, []*Tx{etx}) } -func (o *evmTxStore) loadEthTxesAttemptsReceipts(ctx context.Context, etxs []*Tx) (err error) { +func initEthTxesAttempts(etxs []*Tx) (map[common.Hash]*TxAttempt, [][]byte, bool) { if len(etxs) == 0 { - return nil + return nil, nil, true } + attemptHashM := make(map[common.Hash]*TxAttempt, len(etxs)) // len here is lower bound attemptHashes := make([][]byte, len(etxs)) // len here is lower bound for _, etx := range etxs { @@ -677,6 +678,15 @@ func (o *evmTxStore) loadEthTxesAttemptsReceipts(ctx context.Context, etxs []*Tx attemptHashes = append(attemptHashes, attempt.Hash.Bytes()) } } + return attemptHashM, attemptHashes, false +} + +func (o *evmTxStore) loadEthTxesAttemptsReceipts(ctx context.Context, etxs []*Tx) (err error) { + attemptHashM, attemptHashes, empty := initEthTxesAttempts(etxs) + if empty { + return nil + } + var rs []dbReceipt if err = o.q.SelectContext(ctx, &rs, `SELECT * FROM evm.receipts WHERE tx_hash = ANY($1)`, pq.Array(attemptHashes)); err != nil { return pkgerrors.Wrap(err, "loadEthTxesAttemptsReceipts failed to load evm.receipts") @@ -693,6 +703,37 @@ func (o *evmTxStore) loadEthTxesAttemptsReceipts(ctx context.Context, etxs []*Tx return nil } +// loadEthTxesAttemptsPartialReceipts loads ethTxes with attempts contains partial values for optimization +func (o *evmTxStore) loadEthTxesAttemptsPartialReceipts(ctx context.Context, etxs []*Tx) (err error) { + attemptHashM, attemptHashes, empty := initEthTxesAttempts(etxs) + if empty { + return nil + } + + var rs []dbReceipt + if err = o.q.SelectContext(ctx, &rs, `SELECT evm.receipts.block_hash, evm.receipts.block_number, evm.receipts.transaction_index, evm.receipts.tx_hash FROM evm.receipts WHERE tx_hash = ANY($1)`, pq.Array(attemptHashes)); err != nil { + return pkgerrors.Wrap(err, "loadEthTxesAttemptsReceipts failed to load evm.receipts") + } + + receipts := make([]*evmtypes.Receipt, len(rs)) + for i := 0; i < len(rs); i++ { + receipts[i] = &evmtypes.Receipt{ + BlockHash: rs[i].BlockHash, + BlockNumber: big.NewInt(rs[i].BlockNumber), + TransactionIndex: rs[i].TransactionIndex, + TxHash: rs[i].TxHash, + } + } + + for _, receipt := range receipts { + attempt := attemptHashM[receipt.TxHash] + // Although the attempts struct supports multiple receipts, the expectation for EVM is that there is only one receipt + // per tx and therefore attempt too. + attempt.Receipts = append(attempt.Receipts, receipt) + } + return nil +} + func loadConfirmedAttemptsReceipts(ctx context.Context, q sqlutil.DataSource, attempts []TxAttempt) error { byHash := make(map[string]*TxAttempt, len(attempts)) hashes := make([][]byte, len(attempts)) @@ -1168,7 +1209,9 @@ ORDER BY nonce ASC if err = orm.LoadTxesAttempts(ctx, etxs); err != nil { return pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed to load evm.tx_attempts") } - err = orm.loadEthTxesAttemptsReceipts(ctx, etxs) + + // retrieve tx with attempts which contain partial values for optimization purpose + err = orm.loadEthTxesAttemptsPartialReceipts(ctx, etxs) return pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed to load evm.receipts") }) return etxs, pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed") From cc0c592911a78c5fa479a822b0cd43d37a40addf Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Mon, 5 Aug 2024 17:58:25 -0500 Subject: [PATCH 02/18] update comments, add changeset --- .changeset/cuddly-eels-lay.md | 5 +++++ core/chains/evm/txmgr/evm_tx_store.go | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .changeset/cuddly-eels-lay.md diff --git a/.changeset/cuddly-eels-lay.md b/.changeset/cuddly-eels-lay.md new file mode 100644 index 00000000000..9c11e4e36db --- /dev/null +++ b/.changeset/cuddly-eels-lay.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Improve TXM performance by optimize Confirmer and Finalizer queries to stop pulling EVM receipt. #internal #changed #updated diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index c6a785ae189..865a4102ad6 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -703,7 +703,7 @@ func (o *evmTxStore) loadEthTxesAttemptsReceipts(ctx context.Context, etxs []*Tx return nil } -// loadEthTxesAttemptsPartialReceipts loads ethTxes with attempts contains partial values for optimization +// loadEthTxesAttemptsPartialReceipts loads ethTxes with partial attempts values for optimization func (o *evmTxStore) loadEthTxesAttemptsPartialReceipts(ctx context.Context, etxs []*Tx) (err error) { attemptHashM, attemptHashes, empty := initEthTxesAttempts(etxs) if empty { @@ -1210,7 +1210,7 @@ ORDER BY nonce ASC return pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed to load evm.tx_attempts") } - // retrieve tx with attempts which contain partial values for optimization purpose + // retrieve tx with attempts which contain partial attempts values for optimization purpose err = orm.loadEthTxesAttemptsPartialReceipts(ctx, etxs) return pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed to load evm.receipts") }) From eb8ccba343f5182a2f97ce1670ac9b8f649a6198 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Tue, 6 Aug 2024 10:03:05 -0500 Subject: [PATCH 03/18] update test --- core/chains/evm/txmgr/evm_tx_store_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go index afb8de4ca52..b9beb286493 100644 --- a/core/chains/evm/txmgr/evm_tx_store_test.go +++ b/core/chains/evm/txmgr/evm_tx_store_test.go @@ -840,6 +840,12 @@ func TestORM_FindTransactionsConfirmedInBlockRange(t *testing.T) { assert.Equal(t, etxes[0].Sequence, etx_8.Sequence) assert.Equal(t, etxes[1].Sequence, etx_9.Sequence) }) + + t.Run("return no error when no transactions in range found", func(t *testing.T) { + etxes, err := txStore.FindTransactionsConfirmedInBlockRange(tests.Context(t), 0, 0, ethClient.ConfiguredChainID()) + require.NoError(t, err) + assert.Len(t, etxes, 0) + }) } func TestORM_FindEarliestUnconfirmedBroadcastTime(t *testing.T) { From bf9806a2eb1d646d8593c715809144d7ea92005c Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Tue, 6 Aug 2024 18:12:41 -0500 Subject: [PATCH 04/18] update finalizer query --- core/chains/evm/txmgr/evm_tx_store.go | 4 +++- core/chains/evm/txmgr/finalizer.go | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index a07923a61ea..205aa0c1ed9 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -2122,8 +2122,10 @@ func (o *evmTxStore) FindConfirmedTxesReceipts(ctx context.Context, finalizedBlo var cancel context.CancelFunc ctx, cancel = o.stopCh.Ctx(ctx) defer cancel() + + // note the receipts are partially loaded for performance reason err = o.Transact(ctx, true, func(orm *evmTxStore) error { - sql := `SELECT evm.receipts.* FROM evm.receipts + sql := `SELECT evm.receipts.id, evm.receipts.tx_hash, evm.receipts.block_hash, evm.receipts.block_number FROM evm.receipts INNER JOIN evm.tx_attempts ON evm.tx_attempts.hash = evm.receipts.tx_hash INNER JOIN evm.txes ON evm.txes.id = evm.tx_attempts.eth_tx_id WHERE evm.txes.state = 'confirmed' AND evm.receipts.block_number <= $1 AND evm.txes.evm_chain_id = $2` diff --git a/core/chains/evm/txmgr/finalizer.go b/core/chains/evm/txmgr/finalizer.go index 6d5fb81782c..0a7ed8ab0d5 100644 --- a/core/chains/evm/txmgr/finalizer.go +++ b/core/chains/evm/txmgr/finalizer.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rpc" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" @@ -174,7 +175,7 @@ func (f *evmFinalizer) processFinalizedHead(ctx context.Context, latestFinalized // Find transactions with receipt block nums older than the latest finalized block num and block hashes still in chain for _, receipt := range unfinalizedReceipts { // The tx store query ensures transactions have receipts but leaving this check here for a belts and braces approach - if receipt.Receipt.IsZero() || receipt.Receipt.IsUnmined() { + if receipt.TxHash == utils.EmptyHash || receipt.BlockHash == utils.EmptyHash { f.lggr.AssumptionViolationw("invalid receipt found for confirmed transaction", "receipt", receipt) continue } From ce61bf7a0f0aab8bf8446206a9a2e3de4e2de334 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Tue, 6 Aug 2024 18:21:03 -0500 Subject: [PATCH 05/18] rename --- core/chains/evm/txmgr/evm_tx_store.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index 205aa0c1ed9..bae2f4f3089 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -669,6 +669,9 @@ func (o *evmTxStore) loadEthTxAttemptsReceipts(ctx context.Context, etx *Tx) (er return o.loadEthTxesAttemptsReceipts(ctx, []*Tx{etx}) } +// initEthTxesAttempts takes an input txes slice, return initialized an attempt map and attemptHashes slice, as well as +// +// a third value indicate if the input slice is empty func initEthTxesAttempts(etxs []*Tx) (map[common.Hash]*TxAttempt, [][]byte, bool) { if len(etxs) == 0 { return nil, nil, true @@ -687,8 +690,8 @@ func initEthTxesAttempts(etxs []*Tx) (map[common.Hash]*TxAttempt, [][]byte, bool } func (o *evmTxStore) loadEthTxesAttemptsReceipts(ctx context.Context, etxs []*Tx) (err error) { - attemptHashM, attemptHashes, empty := initEthTxesAttempts(etxs) - if empty { + attemptHashM, attemptHashes, isEmpty := initEthTxesAttempts(etxs) + if isEmpty { return nil } @@ -710,8 +713,8 @@ func (o *evmTxStore) loadEthTxesAttemptsReceipts(ctx context.Context, etxs []*Tx // loadEthTxesAttemptsPartialReceipts loads ethTxes with partial attempts values for optimization func (o *evmTxStore) loadEthTxesAttemptsPartialReceipts(ctx context.Context, etxs []*Tx) (err error) { - attemptHashM, attemptHashes, empty := initEthTxesAttempts(etxs) - if empty { + attemptHashM, attemptHashes, isEmpty := initEthTxesAttempts(etxs) + if isEmpty { return nil } From 0be431fa6f49b2a2db8ebd407d4c8ffed463916c Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Tue, 6 Aug 2024 18:22:58 -0500 Subject: [PATCH 06/18] more rename --- core/chains/evm/txmgr/evm_tx_store.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index bae2f4f3089..8bcd9a118cf 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -711,8 +711,8 @@ func (o *evmTxStore) loadEthTxesAttemptsReceipts(ctx context.Context, etxs []*Tx return nil } -// loadEthTxesAttemptsPartialReceipts loads ethTxes with partial attempts values for optimization -func (o *evmTxStore) loadEthTxesAttemptsPartialReceipts(ctx context.Context, etxs []*Tx) (err error) { +// loadEthTxesAttemptsWithPartialReceipts loads ethTxes with partial attempts values for optimization +func (o *evmTxStore) loadEthTxesAttemptsWithPartialReceipts(ctx context.Context, etxs []*Tx) (err error) { attemptHashM, attemptHashes, isEmpty := initEthTxesAttempts(etxs) if isEmpty { return nil @@ -1219,7 +1219,7 @@ ORDER BY nonce ASC } // retrieve tx with attempts which contain partial attempts values for optimization purpose - err = orm.loadEthTxesAttemptsPartialReceipts(ctx, etxs) + err = orm.loadEthTxesAttemptsWithPartialReceipts(ctx, etxs) return pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed to load evm.receipts") }) return etxs, pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed") From 7c8f7139af3a040f508c7d6e63866019f3adfbc6 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Wed, 7 Aug 2024 10:57:49 -0500 Subject: [PATCH 07/18] fix lint --- core/chains/evm/txmgr/finalizer.go | 1 + 1 file changed, 1 insertion(+) diff --git a/core/chains/evm/txmgr/finalizer.go b/core/chains/evm/txmgr/finalizer.go index 0a7ed8ab0d5..ede0c270dc5 100644 --- a/core/chains/evm/txmgr/finalizer.go +++ b/core/chains/evm/txmgr/finalizer.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rpc" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink-common/pkg/logger" From 6f3e6f77fe25723a98d2a947540015293180b931 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Wed, 7 Aug 2024 13:57:41 -0500 Subject: [PATCH 08/18] minor --- .changeset/cuddly-eels-lay.md | 2 +- core/chains/evm/txmgr/evm_tx_store.go | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.changeset/cuddly-eels-lay.md b/.changeset/cuddly-eels-lay.md index 9c11e4e36db..0262f64ded6 100644 --- a/.changeset/cuddly-eels-lay.md +++ b/.changeset/cuddly-eels-lay.md @@ -2,4 +2,4 @@ "chainlink": minor --- -Improve TXM performance by optimize Confirmer and Finalizer queries to stop pulling EVM receipt. #internal #changed #updated +Improve TXM performance by optimize Confirmer and Finalizer queries to stop pulling EVM receipt. #internal diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index 8bcd9a118cf..b30383b281f 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -669,9 +669,7 @@ func (o *evmTxStore) loadEthTxAttemptsReceipts(ctx context.Context, etx *Tx) (er return o.loadEthTxesAttemptsReceipts(ctx, []*Tx{etx}) } -// initEthTxesAttempts takes an input txes slice, return initialized an attempt map and attemptHashes slice, as well as -// -// a third value indicate if the input slice is empty +// initEthTxesAttempts takes an input txes slice, return initialized an attempt map and attemptHashes slice, plus a third value indicate if the input slice is empty func initEthTxesAttempts(etxs []*Tx) (map[common.Hash]*TxAttempt, [][]byte, bool) { if len(etxs) == 0 { return nil, nil, true From 37199f6d3ac3833bf45fc1a91cde4afc2f5a79a8 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Wed, 7 Aug 2024 14:36:46 -0500 Subject: [PATCH 09/18] Amit comments --- common/txmgr/types/tx_store.go | 2 ++ core/chains/evm/txmgr/evm_tx_store.go | 4 ++-- core/chains/evm/txmgr/evm_tx_store_test.go | 2 +- core/chains/evm/txmgr/finalizer.go | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/common/txmgr/types/tx_store.go b/common/txmgr/types/tx_store.go index 63b56dd169a..e9c7be2f028 100644 --- a/common/txmgr/types/tx_store.go +++ b/common/txmgr/types/tx_store.go @@ -79,6 +79,8 @@ type TransactionStore[ // Search for Tx using the fromAddress and sequence FindTxWithSequence(ctx context.Context, fromAddress ADDR, seq SEQ) (etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindNextUnstartedTransactionFromAddress(ctx context.Context, fromAddress ADDR, chainID CHAIN_ID) (*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) + + // FindTransactionsConfirmedInBlockRange retrieves tx with attempts which contain attempts and partial receipts values for optimization purpose FindTransactionsConfirmedInBlockRange(ctx context.Context, highBlockNumber, lowBlockNumber int64, chainID CHAIN_ID) (etxs []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindEarliestUnconfirmedBroadcastTime(ctx context.Context, chainID CHAIN_ID) (null.Time, error) FindEarliestUnconfirmedTxAttemptBlock(ctx context.Context, chainID CHAIN_ID) (null.Int, error) diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index b30383b281f..9ba05aa4527 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -709,7 +709,7 @@ func (o *evmTxStore) loadEthTxesAttemptsReceipts(ctx context.Context, etxs []*Tx return nil } -// loadEthTxesAttemptsWithPartialReceipts loads ethTxes with partial attempts values for optimization +// loadEthTxesAttemptsWithPartialReceipts loads ethTxes with attempts and partial receipts values for optimization func (o *evmTxStore) loadEthTxesAttemptsWithPartialReceipts(ctx context.Context, etxs []*Tx) (err error) { attemptHashM, attemptHashes, isEmpty := initEthTxesAttempts(etxs) if isEmpty { @@ -1216,7 +1216,7 @@ ORDER BY nonce ASC return pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed to load evm.tx_attempts") } - // retrieve tx with attempts which contain partial attempts values for optimization purpose + // retrieve tx with attempts which contain attempts and partial receipts values for optimization purpose err = orm.loadEthTxesAttemptsWithPartialReceipts(ctx, etxs) return pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed to load evm.receipts") }) diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go index 3a15a434c1c..af4d1ac2b69 100644 --- a/core/chains/evm/txmgr/evm_tx_store_test.go +++ b/core/chains/evm/txmgr/evm_tx_store_test.go @@ -817,7 +817,7 @@ func TestORM_FindTransactionsConfirmedInBlockRange(t *testing.T) { assert.Equal(t, etxes[1].Sequence, etx_9.Sequence) }) - t.Run("return no error when no transactions in range found", func(t *testing.T) { + t.Run("return empty txes when no transactions in range found", func(t *testing.T) { etxes, err := txStore.FindTransactionsConfirmedInBlockRange(tests.Context(t), 0, 0, ethClient.ConfiguredChainID()) require.NoError(t, err) assert.Len(t, etxes, 0) diff --git a/core/chains/evm/txmgr/finalizer.go b/core/chains/evm/txmgr/finalizer.go index ede0c270dc5..80bc2bf6beb 100644 --- a/core/chains/evm/txmgr/finalizer.go +++ b/core/chains/evm/txmgr/finalizer.go @@ -25,6 +25,7 @@ var _ Finalizer = (*evmFinalizer)(nil) const processHeadTimeout = 10 * time.Minute type finalizerTxStore interface { + // FindConfirmedTxesReceipts fetch the txes with partially loaded receipts for performance reason FindConfirmedTxesReceipts(ctx context.Context, finalizedBlockNum int64, chainID *big.Int) ([]Receipt, error) UpdateTxStatesToFinalizedUsingReceiptIds(ctx context.Context, txs []int64, chainId *big.Int) error } From ea4f499d9b36e7570119e9dcc839e03800e18c5f Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Wed, 7 Aug 2024 16:37:51 -0500 Subject: [PATCH 10/18] improve import --- core/chains/evm/txmgr/finalizer.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/chains/evm/txmgr/finalizer.go b/core/chains/evm/txmgr/finalizer.go index 80bc2bf6beb..074ba12a48d 100644 --- a/core/chains/evm/txmgr/finalizer.go +++ b/core/chains/evm/txmgr/finalizer.go @@ -10,13 +10,12 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rpc" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ) var _ Finalizer = (*evmFinalizer)(nil) From 720aba1afccc33ede3ac0ec3d8d466b8307f1be7 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Mon, 12 Aug 2024 13:23:39 -0500 Subject: [PATCH 11/18] Amit comments --- common/txmgr/types/tx_store.go | 2 +- core/chains/evm/txmgr/evm_tx_store.go | 2 +- core/chains/evm/txmgr/finalizer.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/txmgr/types/tx_store.go b/common/txmgr/types/tx_store.go index e9c7be2f028..7ec72ceb1ed 100644 --- a/common/txmgr/types/tx_store.go +++ b/common/txmgr/types/tx_store.go @@ -80,7 +80,7 @@ type TransactionStore[ FindTxWithSequence(ctx context.Context, fromAddress ADDR, seq SEQ) (etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindNextUnstartedTransactionFromAddress(ctx context.Context, fromAddress ADDR, chainID CHAIN_ID) (*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) - // FindTransactionsConfirmedInBlockRange retrieves tx with attempts which contain attempts and partial receipts values for optimization purpose + // FindTransactionsConfirmedInBlockRange retrieves tx with attempts and partial receipt values for optimization purpose FindTransactionsConfirmedInBlockRange(ctx context.Context, highBlockNumber, lowBlockNumber int64, chainID CHAIN_ID) (etxs []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindEarliestUnconfirmedBroadcastTime(ctx context.Context, chainID CHAIN_ID) (null.Time, error) FindEarliestUnconfirmedTxAttemptBlock(ctx context.Context, chainID CHAIN_ID) (null.Int, error) diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index 9ba05aa4527..4d3fbff7e28 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -1216,7 +1216,7 @@ ORDER BY nonce ASC return pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed to load evm.tx_attempts") } - // retrieve tx with attempts which contain attempts and partial receipts values for optimization purpose + // retrieve tx with attempts and partial receipt values for optimization purpose err = orm.loadEthTxesAttemptsWithPartialReceipts(ctx, etxs) return pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed to load evm.receipts") }) diff --git a/core/chains/evm/txmgr/finalizer.go b/core/chains/evm/txmgr/finalizer.go index 074ba12a48d..c0703560a80 100644 --- a/core/chains/evm/txmgr/finalizer.go +++ b/core/chains/evm/txmgr/finalizer.go @@ -24,7 +24,7 @@ var _ Finalizer = (*evmFinalizer)(nil) const processHeadTimeout = 10 * time.Minute type finalizerTxStore interface { - // FindConfirmedTxesReceipts fetch the txes with partially loaded receipts for performance reason + // FindConfirmedTxesReceipts fetches partially loaded receipts for performance reason FindConfirmedTxesReceipts(ctx context.Context, finalizedBlockNum int64, chainID *big.Int) ([]Receipt, error) UpdateTxStatesToFinalizedUsingReceiptIds(ctx context.Context, txs []int64, chainId *big.Int) error } From f274f81597f6d70a6b8a7f722dafc96b460e9dc3 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Mon, 12 Aug 2024 13:25:04 -0500 Subject: [PATCH 12/18] grammar --- core/chains/evm/txmgr/evm_tx_store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index 4d3fbff7e28..156cc21ea28 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -669,7 +669,7 @@ func (o *evmTxStore) loadEthTxAttemptsReceipts(ctx context.Context, etx *Tx) (er return o.loadEthTxesAttemptsReceipts(ctx, []*Tx{etx}) } -// initEthTxesAttempts takes an input txes slice, return initialized an attempt map and attemptHashes slice, plus a third value indicate if the input slice is empty +// initEthTxesAttempts takes an input txes slice, return an initialized attempt map and attemptHashes slice, plus a third value indicate if the input slice is empty func initEthTxesAttempts(etxs []*Tx) (map[common.Hash]*TxAttempt, [][]byte, bool) { if len(etxs) == 0 { return nil, nil, true From 79b71ac0104be201acaa5039c31f85e35da1f815 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Mon, 19 Aug 2024 13:52:37 -0500 Subject: [PATCH 13/18] Dimitris comments --- .changeset/cuddly-eels-lay.md | 2 +- core/chains/evm/txmgr/evm_tx_store.go | 16 +++++++--------- core/chains/evm/txmgr/finalizer.go | 1 - 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/.changeset/cuddly-eels-lay.md b/.changeset/cuddly-eels-lay.md index 0262f64ded6..25b38d3164d 100644 --- a/.changeset/cuddly-eels-lay.md +++ b/.changeset/cuddly-eels-lay.md @@ -2,4 +2,4 @@ "chainlink": minor --- -Improve TXM performance by optimize Confirmer and Finalizer queries to stop pulling EVM receipt. #internal +Improve TXM performance by optimizing Confirmer and Finalizer queries to stop pulling EVM receipt. #internal diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index 6566213a380..3b4f6f484aa 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -2120,19 +2120,17 @@ func (o *evmTxStore) FindConfirmedTxesReceipts(ctx context.Context, finalizedBlo defer cancel() // note the receipts are partially loaded for performance reason - err = o.Transact(ctx, true, func(orm *evmTxStore) error { - sql := `SELECT evm.receipts.id, evm.receipts.tx_hash, evm.receipts.block_hash, evm.receipts.block_number FROM evm.receipts + + query := `SELECT evm.receipts.id, evm.receipts.tx_hash, evm.receipts.block_hash, evm.receipts.block_number FROM evm.receipts INNER JOIN evm.tx_attempts ON evm.tx_attempts.hash = evm.receipts.tx_hash INNER JOIN evm.txes ON evm.txes.id = evm.tx_attempts.eth_tx_id WHERE evm.txes.state = 'confirmed' AND evm.receipts.block_number <= $1 AND evm.txes.evm_chain_id = $2` - var dbReceipts []DbReceipt - err = o.q.SelectContext(ctx, &dbReceipts, sql, finalizedBlockNum, chainID.String()) - if len(dbReceipts) == 0 { - return nil - } + var dbReceipts []DbReceipt + err = o.q.SelectContext(ctx, &dbReceipts, query, finalizedBlockNum, chainID.String()) + if len(dbReceipts) != 0 { receipts = dbReceipts - return nil - }) + } + return receipts, err } diff --git a/core/chains/evm/txmgr/finalizer.go b/core/chains/evm/txmgr/finalizer.go index c0703560a80..60744636159 100644 --- a/core/chains/evm/txmgr/finalizer.go +++ b/core/chains/evm/txmgr/finalizer.go @@ -24,7 +24,6 @@ var _ Finalizer = (*evmFinalizer)(nil) const processHeadTimeout = 10 * time.Minute type finalizerTxStore interface { - // FindConfirmedTxesReceipts fetches partially loaded receipts for performance reason FindConfirmedTxesReceipts(ctx context.Context, finalizedBlockNum int64, chainID *big.Int) ([]Receipt, error) UpdateTxStatesToFinalizedUsingReceiptIds(ctx context.Context, txs []int64, chainId *big.Int) error } From 36f6d4f47372a8f6c08af7983c1d48b6d20b7c07 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Mon, 19 Aug 2024 13:54:08 -0500 Subject: [PATCH 14/18] format --- core/chains/evm/txmgr/evm_tx_store.go | 1 - 1 file changed, 1 deletion(-) diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index 3b4f6f484aa..a5a3edebdcf 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -2120,7 +2120,6 @@ func (o *evmTxStore) FindConfirmedTxesReceipts(ctx context.Context, finalizedBlo defer cancel() // note the receipts are partially loaded for performance reason - query := `SELECT evm.receipts.id, evm.receipts.tx_hash, evm.receipts.block_hash, evm.receipts.block_number FROM evm.receipts INNER JOIN evm.tx_attempts ON evm.tx_attempts.hash = evm.receipts.tx_hash INNER JOIN evm.txes ON evm.txes.id = evm.tx_attempts.eth_tx_id From 47383fd36c57fe138f434d1aa24194092cb6d89b Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Tue, 20 Aug 2024 09:13:20 -0500 Subject: [PATCH 15/18] cleanup --- core/chains/evm/txmgr/evm_tx_store.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index a5a3edebdcf..1e4581a32d4 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -2113,7 +2113,7 @@ func (o *evmTxStore) UpdateTxAttemptBroadcastBeforeBlockNum(ctx context.Context, return err } -// Returns all confirmed transactions with receipt block nums older than or equal to the finalized block number +// FindConfirmedTxesReceipts Returns all confirmed transactions with receipt block nums older than or equal to the finalized block number func (o *evmTxStore) FindConfirmedTxesReceipts(ctx context.Context, finalizedBlockNum int64, chainID *big.Int) (receipts []Receipt, err error) { var cancel context.CancelFunc ctx, cancel = o.stopCh.Ctx(ctx) @@ -2124,12 +2124,7 @@ func (o *evmTxStore) FindConfirmedTxesReceipts(ctx context.Context, finalizedBlo INNER JOIN evm.tx_attempts ON evm.tx_attempts.hash = evm.receipts.tx_hash INNER JOIN evm.txes ON evm.txes.id = evm.tx_attempts.eth_tx_id WHERE evm.txes.state = 'confirmed' AND evm.receipts.block_number <= $1 AND evm.txes.evm_chain_id = $2` - var dbReceipts []DbReceipt - err = o.q.SelectContext(ctx, &dbReceipts, query, finalizedBlockNum, chainID.String()) - if len(dbReceipts) != 0 { - receipts = dbReceipts - } - + err = o.q.SelectContext(ctx, &receipts, query, finalizedBlockNum, chainID.String()) return receipts, err } From 5efdef78fbe23b1373f43902972f9c27f06f0228 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Wed, 21 Aug 2024 10:36:27 -0500 Subject: [PATCH 16/18] format --- core/chains/evm/txmgr/evm_tx_store.go | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index 1e4581a32d4..f648f7f6a07 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -670,11 +670,7 @@ func (o *evmTxStore) loadEthTxAttemptsReceipts(ctx context.Context, etx *Tx) (er } // initEthTxesAttempts takes an input txes slice, return an initialized attempt map and attemptHashes slice, plus a third value indicate if the input slice is empty -func initEthTxesAttempts(etxs []*Tx) (map[common.Hash]*TxAttempt, [][]byte, bool) { - if len(etxs) == 0 { - return nil, nil, true - } - +func initEthTxesAttempts(etxs []*Tx) (map[common.Hash]*TxAttempt, [][]byte) { attemptHashM := make(map[common.Hash]*TxAttempt, len(etxs)) // len here is lower bound attemptHashes := make([][]byte, len(etxs)) // len here is lower bound for _, etx := range etxs { @@ -684,12 +680,12 @@ func initEthTxesAttempts(etxs []*Tx) (map[common.Hash]*TxAttempt, [][]byte, bool } } - return attemptHashM, attemptHashes, false + return attemptHashM, attemptHashes } func (o *evmTxStore) loadEthTxesAttemptsReceipts(ctx context.Context, etxs []*Tx) (err error) { - attemptHashM, attemptHashes, isEmpty := initEthTxesAttempts(etxs) - if isEmpty { + attemptHashM, attemptHashes := initEthTxesAttempts(etxs) + if len(attemptHashes) == 0 { return nil } @@ -711,8 +707,8 @@ func (o *evmTxStore) loadEthTxesAttemptsReceipts(ctx context.Context, etxs []*Tx // loadEthTxesAttemptsWithPartialReceipts loads ethTxes with attempts and partial receipts values for optimization func (o *evmTxStore) loadEthTxesAttemptsWithPartialReceipts(ctx context.Context, etxs []*Tx) (err error) { - attemptHashM, attemptHashes, isEmpty := initEthTxesAttempts(etxs) - if isEmpty { + attemptHashM, attemptHashes := initEthTxesAttempts(etxs) + if len(attemptHashes) == 0 { return nil } From b697075c5585345e91a19a8e88aa3faae67cb1f1 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Wed, 21 Aug 2024 10:40:28 -0500 Subject: [PATCH 17/18] comment --- core/chains/evm/txmgr/evm_tx_store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index f648f7f6a07..1e2cf0ef9cb 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -669,7 +669,7 @@ func (o *evmTxStore) loadEthTxAttemptsReceipts(ctx context.Context, etx *Tx) (er return o.loadEthTxesAttemptsReceipts(ctx, []*Tx{etx}) } -// initEthTxesAttempts takes an input txes slice, return an initialized attempt map and attemptHashes slice, plus a third value indicate if the input slice is empty +// initEthTxesAttempts takes an input txes slice, return an initialized attempt map and attemptHashes slice func initEthTxesAttempts(etxs []*Tx) (map[common.Hash]*TxAttempt, [][]byte) { attemptHashM := make(map[common.Hash]*TxAttempt, len(etxs)) // len here is lower bound attemptHashes := make([][]byte, len(etxs)) // len here is lower bound From 74ad561c0c439aee0c0989de9df9a5a752dfde46 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Wed, 21 Aug 2024 11:04:11 -0500 Subject: [PATCH 18/18] improve --- core/chains/evm/txmgr/evm_tx_store.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index 1e2cf0ef9cb..fa2251168d9 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -684,11 +684,11 @@ func initEthTxesAttempts(etxs []*Tx) (map[common.Hash]*TxAttempt, [][]byte) { } func (o *evmTxStore) loadEthTxesAttemptsReceipts(ctx context.Context, etxs []*Tx) (err error) { - attemptHashM, attemptHashes := initEthTxesAttempts(etxs) - if len(attemptHashes) == 0 { + if len(etxs) == 0 { return nil } + attemptHashM, attemptHashes := initEthTxesAttempts(etxs) var rs []DbReceipt if err = o.q.SelectContext(ctx, &rs, `SELECT * FROM evm.receipts WHERE tx_hash = ANY($1)`, pq.Array(attemptHashes)); err != nil { return pkgerrors.Wrap(err, "loadEthTxesAttemptsReceipts failed to load evm.receipts") @@ -707,11 +707,11 @@ func (o *evmTxStore) loadEthTxesAttemptsReceipts(ctx context.Context, etxs []*Tx // loadEthTxesAttemptsWithPartialReceipts loads ethTxes with attempts and partial receipts values for optimization func (o *evmTxStore) loadEthTxesAttemptsWithPartialReceipts(ctx context.Context, etxs []*Tx) (err error) { - attemptHashM, attemptHashes := initEthTxesAttempts(etxs) - if len(attemptHashes) == 0 { + if len(etxs) == 0 { return nil } + attemptHashM, attemptHashes := initEthTxesAttempts(etxs) var rs []DbReceipt if err = o.q.SelectContext(ctx, &rs, `SELECT evm.receipts.block_hash, evm.receipts.block_number, evm.receipts.transaction_index, evm.receipts.tx_hash FROM evm.receipts WHERE tx_hash = ANY($1)`, pq.Array(attemptHashes)); err != nil { return pkgerrors.Wrap(err, "loadEthTxesAttemptsReceipts failed to load evm.receipts")