Skip to content

Fix ethereum mempool/address index consistency#1

Open
ak-ux wants to merge 1 commit into
mycelium-com:masterfrom
ak-ux:fix/eth-mempool-consistency
Open

Fix ethereum mempool/address index consistency#1
ak-ux wants to merge 1 commit into
mycelium-com:masterfrom
ak-ux:fix/eth-mempool-consistency

Conversation

@ak-ux
Copy link
Copy Markdown

@ak-ux ak-ux commented Apr 21, 2026

Summary

Address-level API responses silently drop pending txs that blockbook's in-memory mempool has evicted, while per-tx responses still return them from the backend. This produces visible inconsistency to API consumers (e.g. wallets showing /api/v2/tx/{hash} as pending but /api/v2/address/{addr} returning unconfirmedTxs: 0).

Root causes

  1. MempoolEthereumType.Resync() enforces a 48h timeout eviction on its txEntries / addrDescToTx maps. Without queryBackendOnMempoolResync, nothing re-populates them — long-lived pending txs disappear from address queries even though the backend still holds them.

  2. GetMempoolTransactions() sources from eth_getBlockByNumber("pending"), which only returns executable pending txs (nonce = last_confirmed + 1 and contiguous). Nonce-gap txs in the queued pool are invisible, so even with re-sync enabled they can't be re-hydrated.

Changes

  • configs/coins/ethereum.json: flip queryBackendOnMempoolResync to true.
  • bchain/coins/eth/ethrpc.go: prefer txpool_content (both pending and queued buckets) when the txpool namespace is available; fall back to the pending-block view otherwise.

Erigon is started with --http.api "eth,net,web3,debug,txpool" in the current ethereum.json config, so the new RPC path is available out of the box.

Test plan

  • Deploy to a blockbook-eth instance with long-lived pending txs in the address's mempool.
  • GET /api/v2/address/{addr} → confirm unconfirmedTxs reflects the geth mempool count.
  • GET /api/v2/address/{addr}?details=txs → confirm pending txs appear at the top of transactions.
  • GET /api/v2/tx/{hash} for a nonce-gap queued tx → should still return pending status.

🤖 Generated with Claude Code

The address-level API responses were silently dropping pending txs that
blockbook's in-memory mempool had evicted, while per-tx responses still
returned them from the backend. Two root causes:

1. MempoolEthereumType.Resync() enforces a 48h timeout-based eviction on
   its txEntries / addrDescToTx maps. Without `queryBackendOnMempoolResync`,
   nothing ever re-populates them, so long-lived pending txs disappear from
   address queries even though the backend still holds them.

   -> Flip queryBackendOnMempoolResync to true in configs/coins/ethereum.json.

2. GetMempoolTransactions() sourced from eth_getBlockByNumber("pending"),
   which only returns *executable* pending txs (nonce = last_confirmed + 1
   and contiguous). Nonce-gap txs sitting in the queued pool were invisible,
   so even with queryBackendOnMempoolResync=true they couldn't be re-hydrated.

   -> Prefer txpool_content (available when the txpool namespace is
      enabled, as it is with the current Erigon config). Fall back to the
      pending-block view if the namespace isn't available.

Symptoms: /api/v2/tx/{hash} returns a pending tx with confirmations=0 and
status=-1, but /api/v2/address/{addr}?details=txs omits it and
/api/v2/address/{addr} shows unconfirmedTxs=0. After these changes both
endpoints agree for the duration the tx is held by the backend.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants