Skip to content

fix(rpc): fall through to CometBFT on KV indexer miss to serve derive…#14

Open
AryaLanjewar3005 wants to merge 6 commits into
feat/derived-txfrom
feat/derived-tx-evm-0.4.0
Open

fix(rpc): fall through to CometBFT on KV indexer miss to serve derive…#14
AryaLanjewar3005 wants to merge 6 commits into
feat/derived-txfrom
feat/derived-tx-evm-0.4.0

Conversation

@AryaLanjewar3005

Copy link
Copy Markdown
Collaborator

…d tx receipts

Description

fix(rpc): fall through to CometBFT on KV indexer miss to serve derived tx receipts

Problem

On the donut testnet, Blockscout was indexing only 15–22% of blocks per day after the evm-v0-4-0 upgrade, leaving ~80% of blocks silently unindexed.

Push Chain produces two classes of EVM transactions:

  • Native txs (MsgEthereumTx) — signed by a user wallet, stored in the KV indexer
  • Derived txs (DerivedEVMCall) — auto-generated by Cosmos modules (x/uexecutor, x/utss) for Universal Transactions inbound from Solana, Ethereum, BNB, Arbitrum etc.

Both types are included in the transactions[] array returned by eth_getBlockByNumber. However, eth_getTransactionReceipt returned null for derived tx hashes because kv_indexer.go only stores native txs — it skips everything that isn't a MsgEthereumTx:

// indexer/kv_indexer.go
if !isEthTx(tx) {
    continue  // derived txs are never written to the KV index
}

When GetTxByEthHash was called with a derived hash, the KV indexer returned "not found" and the function immediately returned an error — never attempting the CometBFT fallback that sits below it and is fully capable of resolving derived txs.

Before v0.4.0, the upstream change 8fb90ba2 ("get receipt should not return error on tx not found") had the node returning (nil, err) for missing receipts, which the RPC layer surfaced as a JSON-RPC error response. Blockscout handled errors gracefully by skipping those hashes. After 8fb90ba2, the same miss returns (nil, nil), which the RPC layer surfaces as a JSON-RPC null result. Blockscout treats null differently — it keeps the hash in its processing pipeline and crashes with a KeyError when the receipt is absent from the merge map. The crash discards the entire block, including native txs that had valid receipts.

We confirmed this live on the unpatched testnet: 4 out of 6 sampled transactions were derived txs with null receipts. In 3 out of 5 sampled blocks, every transaction was a derived tx — meaning Blockscout crashed on the whole block and recorded nothing.

Root Cause

GetTxByEthHash short-circuited on a KV miss instead of falling through to the CometBFT indexer:

// Before
if b.Indexer != nil {
    txRes, err := b.Indexer.GetByTxHash(hash)
    if err != nil {
        return nil, nil, err  // gave up here — CometBFT never tried
    }
    return txRes, nil, nil
}
// CometBFT fallback — unreachable for derived txs

Fix

When the KV indexer returns "not found", fall through to the CometBFT query instead of returning immediately:

// After
if b.Indexer != nil {
    txRes, err := b.Indexer.GetByTxHash(hash)
    if err == nil {
        return txRes, nil, nil
    }
    // KV miss — fall through to CometBFT for derived txs
}
// CometBFT fallback — now reached on KV miss

The CometBFT path was already capable of handling derived txs. Derived txs emit ethereum_tx events with the ethereumTxHash attribute when they execute (x/vm/keeper/call_evm.go), so TxSearch finds them. ParseTxIndexerResult detects DerivedTxType (99) and returns both a TxResult and a populated TxResultAdditionalFields. GetTransactionReceipt then builds a complete receipt from those additional fields via parseDerivedTxFromAdditionalFields — the same path already used by eth_getBlockByNumber to surface derived txs in the block view.

The same fix is applied to GetTxByEthHashAndMsgIndex which has the identical pattern.

Impact

  • eth_getTransactionReceipt now returns a real receipt for derived tx hashes
  • Blockscout receives receipts for all hashes in a block — no crash, full block indexed
  • Native txs continue to use the fast KV path unchanged; the CometBFT fallback is only hit on a KV miss
  • No state migration, no re-indexing, no schema changes — rolling node restart is sufficient

Testing

  • Added TestGetTxByEthHash_DerivedTxFallthrough — sets up a KV indexer that always returns "not found", mocks CometBFT to return a derived tx event response, and asserts that GetTxByEthHash returns non-nil TxResultAdditionalFields with Type == DerivedTxType, correct sender and recipient
  • Added TestGetTxByEthHash_NativeTxKVHit — regression test asserting native txs still return directly from KV without touching CometBFT
  • All existing ./rpc/... tests pass

Files Changed

  • rpc/backend/tx_info.go — fallthrough fix in GetTxByEthHash and GetTxByEthHashAndMsgIndex
  • rpc/backend/tx_info_derived_test.go — new tests for the fix

Author Checklist

All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.

I have...

  • tackled an existing issue or discussed with a team member
  • left instructions on how to review the changes
  • targeted the main branch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant