Integrity

RPC nodes may return stale or inconsistent data. eRPC's integrity module ensures you always get the most recent and valid blockchain data through:

  1. Block tracking — Monitors highest known block across all upstreams, ensures eth_blockNumber and eth_getBlockByNumber(latest/finalized) return the freshest data.
  2. Range enforcement — For eth_getLogs, ensures the requested block range is available on the chosen upstream.
  3. Response validation — Validates response structure and consistency (bloom filters, receipts, logs). See Validations.

Combine with retry and consensus policies for automatic failover when integrity checks fail.

Config

projects:
  - id: main
    networks:
      - architecture: evm
        evm:
          chainId: 1
          # Block tracking: ensure highest known block is returned
          integrity:
            enforceHighestBlock: true       # Replace stale block numbers with highest known
            enforceGetLogsBlockRange: true  # Skip upstreams that don't have requested range
 
    # State poller settings (how block tracking works)
    upstreamDefaults:
      evm:
        statePollerInterval: 30s  # How often to poll latest/finalized block
        statePollerDebounce: 5s   # Min interval between polls (ideally ≤ block time)

Block Tracking

eRPC runs a background state poller for each upstream to track latest/finalized blocks. When enforceHighestBlock: true:

  • eth_blockNumber: If response is older than highest known, returns highest known instead.
  • eth_getBlockByNumber(latest/finalized): If response is stale, retries on other upstreams.

The poller also updates proactively when eth_blockNumber or eth_getBlockByNumber(latest) returns a higher block than currently tracked.

Metrics: erpc_upstream_stale_latest_block_total, erpc_upstream_stale_finalized_block_total

Range Enforcement for eth_getLogs

When enforceGetLogsBlockRange: true, eRPC checks that the upstream has the requested block range before sending the request:

  1. If toBlock > upstream's latest block → skip to next upstream (after forcing a fresh poll if stale)
  2. If fromBlock < upstream's available range (based on maxAvailableRecentBlocks config) → skip to next upstream

Large range handling: eRPC can auto-split large ranges based on getLogsAutoSplittingRangeThreshold or when upstream returns "range too large" errors.

Metrics: erpc_upstream_evm_get_logs_stale_upper_bound_total, erpc_upstream_evm_get_logs_stale_lower_bound_total, erpc_upstream_evm_get_logs_forced_splits_total

Validations Directives

Response validation directives are ideal for high-integrity use-cases (such as indexing) where you need guaranteed data accuracy. When a validation fails, eRPC treats it as an upstream error — the response is rejected and retry/consensus policies automatically try other upstreams until valid data is found.

How it works with failsafe policies:

Request → Upstream A returns receipts with missing logs (logsBloom doesn't match actual logs)
        → Validation fails → Response rejected (not cached, not returned)
        → Retry policy kicks in → Try Upstream B
        → Upstream B returns complete receipts with matching bloom → Success!

With retry: Each validation failure triggers the next retry attempt. Configure maxAttempts high enough to cover your upstream pool.

With consensus: Invalid responses are excluded from consensus voting. Only valid responses participate, so even if 2/3 upstreams return bad data, the 1 valid response wins.

With hedge + consensus + retry (recommended for indexers): Hedge spawns parallel requests, consensus compares valid responses, retry handles cases where all initial attempts fail validation.

Set via config (applies to all requests), HTTP headers, or query parameters:

DirectiveHeaderQueryDescription
validateLogsBloomEmptinessX-ERPC-Validate-Logs-Bloom-Emptinessvalidate-logs-bloom-emptinessBloom/logs consistency: logs exist ↔ bloom non-zero
validateLogsBloomMatchX-ERPC-Validate-Logs-Bloom-Matchvalidate-logs-bloom-matchRecalculate bloom from logs and verify match
enforceLogIndexStrictIncrementsX-ERPC-Enforce-Log-Index-Strict-Incrementsenforce-log-index-strict-incrementsLog indices must increment by 1 across receipts
validateTxHashUniquenessX-ERPC-Validate-Tx-Hash-Uniquenessvalidate-tx-hash-uniquenessNo duplicate transaction hashes in receipts
validateTransactionIndexX-ERPC-Validate-Transaction-Indexvalidate-transaction-indexReceipt indices must be sequential (0, 1, 2...)
validateHeaderFieldLengthsX-ERPC-Validate-Header-Field-Lengthsvalidate-header-field-lengthsBlock header field byte lengths
validateTransactionFieldsX-ERPC-Validate-Transaction-Fieldsvalidate-transaction-fieldsTransaction field formats
validateTransactionBlockInfoX-ERPC-Validate-Transaction-Block-Infovalidate-transaction-block-infoTx block hash/number matches block
validateLogFieldsX-ERPC-Validate-Log-Fieldsvalidate-log-fieldsLog address/topic lengths
receiptsCountExactX-ERPC-Receipts-Count-Exactreceipts-count-exactReceipts array must have exactly N items
receiptsCountAtLeastX-ERPC-Receipts-Count-At-Leastreceipts-count-at-leastReceipts array must have at least N items
validationExpectedBlockHashX-ERPC-Validation-Expected-Block-Hashvalidation-expected-block-hashAll receipts must have this block hash
validationExpectedBlockNumberX-ERPC-Validation-Expected-Block-Numbervalidation-expected-block-numberAll receipts must have this block number
projects:
  - id: main
    networks:
      - architecture: evm
        evm:
          chainId: 1
        directiveDefaults:
          # Response validations are DISABLED by default (to avoid JSON parsing overhead).
          # Enable specific ones as needed for high-integrity use-cases:
          validateLogsBloomEmptiness: true
          validateLogsBloomMatch: true
          enforceLogIndexStrictIncrements: true
          # etc.
        # Recommended for indexers: hedge + consensus + retry
        # Invalid responses are rejected, valid ones are compared, retries if all fail
        failsafe:
          - matchMethods: "eth_getBlockReceipts"
            hedge:
              maxCount: 3 # Spawn up to 3 parallel requests
              delay: 100ms
            consensus:
              maxParticipants: 3
              agreementThreshold: 2 # Accept if 2+ agree (invalid ones excluded)
            retry:
              maxAttempts: 5 # Keep trying until valid data found