Fetch transaction by hash in a single query

This commit is contained in:
Prathamesh Musale 2022-07-07 11:11:45 +05:30
parent fb9168c00b
commit 70fb85cd4a

View File

@ -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