From 70fb85cd4aee6cd4991c64b91b842b9be79ad6b1 Mon Sep 17 00:00:00 2001 From: prathamesh0 Date: Thu, 7 Jul 2022 11:11:45 +0530 Subject: [PATCH] Fetch transaction by hash in a single query --- pkg/eth/backend.go | 62 ++++++++++++++-------------------------------- 1 file changed, 19 insertions(+), 43 deletions(-) diff --git a/pkg/eth/backend.go b/pkg/eth/backend.go index 77b5664e..a5a8e34c 100644 --- a/pkg/eth/backend.go +++ b/pkg/eth/backend.go @@ -52,11 +52,11 @@ import ( ) var ( - errPendingBlockNumber = errors.New("pending block number not supported") - errNegativeBlockNumber = errors.New("negative block number not supported") - errHeaderHashNotFound = errors.New("header for hash not found") - errHeaderNotFound = errors.New("header not found") - errTxHashNotFound = errors.New("transaction for hash not found") + errPendingBlockNumber = errors.New("pending block number not supported") + errNegativeBlockNumber = errors.New("negative block number not supported") + errHeaderHashNotFound = errors.New("header for hash not found") + errHeaderNotFound = errors.New("header not found") + errTxHashInMultipleBlocks = errors.New("transaction for hash found in more than one canonical block") // errMissingSignature is returned if a block's extra-data section doesn't seem // to contain a 65 byte secp256k1 signature. @@ -72,15 +72,12 @@ const ( WHERE block_hash = (SELECT canonical_header_hash($1))` RetrieveTD = `SELECT CAST(td as Text) FROM eth.header_cids WHERE header_cids.block_hash = $1` - RetrieveBlocksByTxHash = `SELECT block_number, header_id FROM from eth.transaction_cids - WHERE tx_hash = $1` - RetrieveRPCTransaction = `SELECT blocks.data, index - FROM public.blocks, eth.transaction_cids, eth.header_cids + RetrieveRPCTransaction = `SELECT blocks.data, header_id, transaction_cids.block_number, index + FROM public.blocks, eth.transaction_cids WHERE blocks.key = transaction_cids.mh_key AND blocks.block_number = transaction_cids.block_number AND transaction_cids.tx_hash = $1 - AND transaction_cids.header_id = $2 - AND transaction_cids.block_number = $3` + AND transaction_cids.header_id = (SELECT canonical_header_hash(transaction_cids.block_number))` RetrieveCodeHashByLeafKeyAndBlockHash = `SELECT code_hash FROM eth.state_accounts, eth.state_cids, eth.header_cids WHERE state_accounts.header_id = state_cids.header_id AND state_accounts.state_path = state_cids.state_path @@ -522,49 +519,28 @@ func (b *Backend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Blo // GetTransaction retrieves a tx by hash // It also returns the blockhash, blocknumber, and tx index associated with the transaction func (b *Backend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { - type txBlock struct { - BlockNumber uint64 `db:"block_number"` + type txRes struct { + Data []byte `db:"data"` HeaderID string `db:"header_id"` + BlockNumber uint64 `db:"block_number"` + Index uint64 `db:"index"` } - - // get number and hash of blocks having the given txHash - txBlockRes := make([]txBlock, 0) - if err := b.DB.Select(&txBlockRes, RetrieveBlocksByTxHash, txHash.String()); err != nil { + var res = make([]txRes, 0) + if err := b.DB.Get(&res, RetrieveRPCTransaction, txHash.String()); err != nil { return nil, common.Hash{}, 0, 0, err } - // filter out non-canonical blocks - var canonicalTxBlock txBlock - for _, res := range txBlockRes { - canonicalHash, err := b.GetCanonicalHash(res.BlockNumber) - if err != nil { - return nil, common.Hash{}, 0, 0, err - } - - if res.HeaderID == canonicalHash.String() { - canonicalTxBlock = res - break - } - } - - if canonicalTxBlock == (txBlock{}) { - return nil, common.Hash{}, 0, 0, errTxHashNotFound - } - - var tempTxStruct struct { - Data []byte `db:"data"` - Index uint64 `db:"index"` - } - if err := b.DB.Get(&tempTxStruct, RetrieveRPCTransaction, txHash.String(), canonicalTxBlock.HeaderID, canonicalTxBlock.BlockNumber); err != nil { - return nil, common.Hash{}, 0, 0, err + // a transaction can be part of a only one canonical block + if len(res) > 1 { + return nil, common.Hash{}, 0, 0, errTxHashInMultipleBlocks } var transaction types.Transaction - if err := transaction.UnmarshalBinary(tempTxStruct.Data); err != nil { + if err := transaction.UnmarshalBinary(res[0].Data); err != nil { return nil, common.Hash{}, 0, 0, err } - return &transaction, common.HexToHash(canonicalTxBlock.HeaderID), canonicalTxBlock.BlockNumber, tempTxStruct.Index, nil + return &transaction, common.HexToHash(res[0].HeaderID), res[0].BlockNumber, res[0].Index, nil } // GetReceipts retrieves receipts for provided block hash