Skip to content

[BUG] RpcClient.call() quarantines healthy endpoints on application-level errors, enabling single-request DoS of the RPC layer #182

Description

@N-thnI

Priority: High

Description

RpcClient.call() quarantines an endpoint for 30s on any exception from the callback, without distinguishing network/connectivity failures from application-level errors (malformed XDR, validation errors). Since call() retries up to MAX_RETRIES=3 times on a new endpoint each time, one bad request can cascade-quarantine up to 3 healthy endpoints simultaneously.

Location

engine-bridge/src/rpc-client.ts:30-48 (call)

Current Behavior

try {
  const server = new SorobanRpc.Server(ep.url, {...});
  return await fn(server);
} catch (err) {
  lastError = err;
  ep.deadUntil = Date.now() + QUARANTINE_MS; // any error at all
  logger.warn(`[RpcClient] ${ep.url} quarantined -- ${(err as Error).message}`);
}

Expected Behavior

Only network/transport-level errors (timeouts, connection refused, 5xx) should quarantine an endpoint; application-level errors that will fail identically everywhere should propagate immediately without punishing the endpoint.

Repro / Evidence

Construct RpcClient with 3 URLs, make fn synchronously throw new Error("invalid XDR"); observe all 3 endpoints' deadUntil set after a single call().

Impact

A single malformed/invalid submission can quarantine every configured RPC endpoint for 30s, denying service to all other concurrent callers of the shared RpcClient (used by EventPropagator, HeartbeatMonitor, GasOracle, NonceManager, TxAggregator) — a low-cost, repeatable self-inflicted DoS.

Suggested Fix

Classify errors before quarantining — only quarantine on network/transport failures; rethrow application-level errors immediately without marking the endpoint dead.

Acceptance Criteria

  • AC-1: A validation/application error doesn't set deadUntil.
  • AC-2: A network/timeout error still quarantines as today.
  • AC-3: New test reproducing the cascade — fails on current code.

Definition of Done

  • Fix merged with all AC items checked
  • Regression test passes in CI
  • No new eslint warnings

Metadata

Metadata

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26Third CampaignCampaign: Third CampaignbugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions