Skip to content

eth: every gas estimate is sent to the alternative provider, burning its rate-limit quota #1629

Description

@cranycrane

Problem

EthereumTypeEstimateGas (bchain/coins/eth/ethrpc.go:1961, provider block at ~1985) routes every eth_estimateGas request to the alternative send-tx provider's urls[0] whenever *_ALTERNATIVE_SENDTX_URLS is configured — the guard is a bare nil-check, with a fresh RPC client dialed per call and a silent fallback to the primary backend on error (the provider error is discarded, so the problem is invisible in logs).

This is the same pathology as #1627, one function further down the file: the routing is unconditional, but almost no request needs the provider. The path is hit from the websocket estimateFee handler (server/websocket.go:1124) — i.e. every time a user sits on a wallet's send screen, with estimates re-firing as the amount is edited.

Example

  • An ETH instance has ETH_ALTERNATIVE_SENDTX_URLS pointed at a private relay whose API key allows ~10 req/s.
  • Alice types an amount into the send form. The wallet requests a gas estimate; Blockbook sends eth_estimateGas to the relay, although Alice never submitted a private transaction — the primary backend could have answered, and the relay call spends quota for nothing.
  • With ~50 users composing transactions concurrently, the relay quota is exhausted → 429s → every estimate pays a wasted round-trip (dial + call + rejection) before the primary answers, making the send form slower for everyone.
  • Bob, who actually just broadcast a private transaction through the relay, is the one harmed: the quota his nonce lookup and next broadcast need was burned by everyone else's gas estimates.

Why not simply "never use the provider for estimates"

There is one legitimate case: a sender with a private transaction still pending. If Bob composes a second transaction that builds on the pending state of his first (private) one, only the relay sees that pending transaction and can estimate correctly — the primary backend cannot.

Proposed fix

Reuse the gating introduced by #1628 for nonces: route eth_estimateGas through the alternative provider only for recent private senders (useForNonces / the recentSenders map), directed at the URL that accepted their send (nonceURL); all other requests go straight to the primary backend. Also stop discarding the provider error silently — log it at warning level like the nonce fallback does.

Related: #1627, #1628 (deliberately scoped the estimateGas path out).

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions