eth_getLogs のブロック範囲制限と分割クエリ

eth_getLogs のブロック範囲制限と logs_range_too_large エラーに対処します。各チェーンの max_logs_block_range を取得し、広い範囲のクエリを分割します。

要点

1 回の eth_getLogs リクエストの上限は、GET /v1/chains で公開されている対象チェーンの max_logs_block_range です(HyperEVM では 1,000 ブロック)。ブロック数は toBlock − fromBlock + 1 で数えます。上限を超えると HTTP 200、JSON-RPC -32602、error.data.reason: logs_range_too_large が返され、retryable: false になります(エラー一覧を参照)。範囲を [from, min(from + max − 1, end)] に分割し、成功したら直前の分割範囲の終了ブロックに 1 を足した位置に進みます。

次のコードを logs-minimal.mjs として保存し、BLOCKVECTRA_API_KEY、コントラクトアドレス LOG_ADDRESS、確認済みのブロック範囲を表す FROM_BLOCK と TO_BLOCK を設定してから、Node.js 24 以降で node logs-minimal.mjs を実行してください。CHAIN でチェーンを選択します。デフォルトは robinhood_mainnet です。

const { BLOCKVECTRA_API_KEY: key, LOG_ADDRESS: address, FROM_BLOCK, TO_BLOCK } = process.env;
if (!key || !/^0x[0-9a-f]{40}$/i.test(address ?? '')) throw new Error('Set BLOCKVECTRA_API_KEY and LOG_ADDRESS');
if (![FROM_BLOCK, TO_BLOCK].every(value => /^(0x[0-9a-f]+|[0-9]+)$/i.test(value ?? ''))) {
  throw new Error('Set FROM_BLOCK and TO_BLOCK to nonnegative block numbers');
}
const start = BigInt(FROM_BLOCK), end = BigInt(TO_BLOCK);
if (start > end) throw new Error('FROM_BLOCK must not exceed TO_BLOCK');
const chainSlug = process.env.CHAIN ?? 'robinhood_mainnet';
const chainsUrl = 'https://api.blockvectra.com/v1/chains';
const catalogResponse = await fetch(chainsUrl, { signal: AbortSignal.timeout(15_000) });
if (!catalogResponse.ok) throw new Error(`Chains HTTP ${catalogResponse.status}`);
const catalog = await catalogResponse.json();
const chain = catalog.chains.find(item => item.chain === chainSlug);
if (!chain || !Number.isSafeInteger(chain.max_logs_block_range) || chain.max_logs_block_range <= 0) {
  throw new Error('Missing or invalid max_logs_block_range');
}
const matches = pattern => pattern.endsWith('*') ? 'eth_getLogs'.startsWith(pattern.slice(0, -1)) : pattern === 'eth_getLogs';
if (!chain.methods?.allow?.some(matches) || chain.methods?.deny?.some(matches)) {
  throw new Error('eth_getLogs is unavailable on this chain');
}
const max = BigInt(chain.max_logs_block_range);
const rpcUrl = new URL(`./${chainSlug}`, chainsUrl).href;
const hex = value => `0x${value.toString(16)}`;
for (let from = start; from <= end;) {
  const to = from + max - 1n < end ? from + max - 1n : end;
  const response = await fetch(rpcUrl, {
    method: 'POST', redirect: 'error', signal: AbortSignal.timeout(15_000),
    headers: { 'Content-Type': 'application/json', 'x-api-key': key },
    body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'eth_getLogs',
      params: [{ address, fromBlock: hex(from), toBlock: hex(to) }] }),
  });
  const body = await response.json();
  if (!response.ok || body.error || !Array.isArray(body.result)) {
    throw new Error(`RPC HTTP ${response.status}: ${JSON.stringify(body.error ?? 'Invalid result')}`);
  }
  console.log(JSON.stringify({ fromBlock: hex(from), toBlock: hex(to), result: body.result }));
  from = to + 1n;
}

出力の各行は、処理が完了した 1 つの分割範囲を表します。HTTP または JSON-RPC エラーが発生すると、失敗した分割範囲をスキップせずにサンプルの実行を停止します。429 への対処については、以下のバッチとレート制限の説明を参照してください。

eth_getLogs のブロック範囲制限

JSON-RPC の eth_getLogs メソッドを呼び出す際、1 回のリクエストのブロック範囲は toBlock − fromBlock + 1 で計算され、対象チェーンが公開している max_logs_block_range を超えることはできません。

この上限はチェーンによって異なります。チェーンごとのパラメータは、公開エンドポイント GET /v1/chains で公開されています(チェーンの一覧は対応チェーンを参照)。このエンドポイントは認証不要で、課金対象外です。クライアントアプリケーションの開発では、ブロック範囲の上限をコードに固定値として埋め込まず、実行時にこのエンドポイントを動的に問い合わせてください。

フィルタフィールド fromBlock と toBlock は、省略した場合や null の場合、デフォルトで latest になります。

チェーンごとの eth_getLogs の制限

以下は、GET /v1/chains で公開されている各チェーンの max_logs_block_range の値です。「未公開」は無制限という意味ではありません。呼び出す前に methods.allow と methods.deny も確認してください。拒否の指定が優先されます。ブロック範囲の上限は、結果件数やクエリ実行時間の上限とは別のものです。

チェーンチェーン識別子max_logs_block_range(ブロック数)
Arbitrum Onearb_mainnet1,000
Basebase_mainnet1,000
BNB Smart Chainbsc_mainnet1,000
Ethereumeth_mainnet1,000
Ethereum Sepoliaeth_sepolia1,000
HyperEVMhyperevm_mainnet1,000
Polygonpolygon_mainnet1,000
Robinhood Chainrobinhood_mainnet1,000
Robinhood Chain Testnetrobinhood_testnet1,000

よくあるエラーメッセージの原文

ブロック範囲、結果件数、クエリ実行時間を区別してください。同じ JSON-RPC コードが異なる失敗を表す場合があります。

エラー文 / 識別子出典対処方法
eth_getLogs block range too large: max <N> blocks; -32602; logs_range_too_largeBlockVectra のエラー一覧<N> はチェーンの max_logs_block_range です。範囲を縮小してから再送してください。変更せずに再試行しても解決しません。
query block range exceeds server limit, narrow your filter: <N>Erigon の eth_getLogs ソースコード<N> はそのノードの範囲上限です。問い合わせる範囲を縮小してから再送してください。
query returns too many logs, narrow your filter: <N>Erigon の eth_getLogs ソースコード<N> はそのノードの結果件数上限です。範囲を縮小し、address と topics の条件を絞り込んでください。1 ブロックだけでも、より具体的なフィルタが必要な場合があります。

これらのメッセージのテンプレートでは、<N> はエンドポイントの上限に置き換えられます。サードパーティーのメッセージは、その提供元のエンドポイントと上限を指しており、文言はクライアントのバージョンによって異なる場合があります。BlockVectra では、/v1/chains と error.data.reason を使用してください。

ブロック範囲の上限を超えた場合

1 回のリクエストのブロック範囲 toBlock − fromBlock + 1 がチェーンの max_logs_block_range を超えると、リクエストは拒否され、HTTP 200 と JSON-RPC エラーが返されます。

  • エラーコード:-32602
  • エラーメッセージ:eth_getLogs block range too large: max <N> blocks
  • 課金状況:課金対象外。

リクエスト例

次のリクエストが上限を超えるのは、そのブロック範囲が対象チェーンの現在の max_logs_block_range より大きい場合のみです。

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_getLogs",
  "params": [
    {
      "fromBlock": "0x45a2409",
      "toBlock": "0x45a27f1"
    }
  ]
}

レスポンス例

対応するエラーレスポンスの例です。

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32602,
    "message": "eth_getLogs block range too large: max <N> blocks"
  }
}

<N> は、対象チェーンの max_logs_block_range です(GET /v1/chains で公開されています)。

複数のコールを含むバッチリクエストで、ある eth_getLogs コールがブロック範囲の上限を超えた場合、その項目に対して上記の -32602 エラーが返され、その項目は課金対象外となります。

分割クエリの実行

広いブロック範囲のログを取得するには、まず対象チェーンの max_logs_block_range を取得し、対象範囲を [from, from + max - 1] の連続した範囲に分割して、結果を集約しながらリクエストを順番に送信します。

以下の例では、robinhood_mainnet を使って分割クエリを示します。

export BLOCKVECTRA_API_KEY="rgw_your_api_key"

# 1. Read max_logs_block_range from the public chains endpoint (unauthenticated, unbilled)
curl -s "https://api.blockvectra.com/v1/chains"

# 2. Make a single compliant request within the chain's max_logs_block_range (toBlock - fromBlock + 1)
curl -s "https://api.blockvectra.com/v1/robinhood_mainnet" \
  -H 'Content-Type: application/json' \
  -H "x-api-key: $BLOCKVECTRA_API_KEY" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getLogs",
    "params": [{
      "address": "0x1111111111111111111111111111111111111111",
      "fromBlock": "0x45a2409",
      "toBlock": "0x45a246c"
    }]
  }'

バッチリクエストの注意点

複数の分割クエリを 1 つの JSON-RPC バッチリクエストにまとめる場合は、バッチとバースト容量のルールに注意してください。

  • バッチサイズの上限:バッチリクエストは 1 ~ 100 コールを受け付けます。100 コールを超えると拒否され、HTTP 200 とエラーコード -32600 batch too large: max 100 calls が返されます(課金対象外)。
  • 1 リクエストのバースト容量:1 回のリクエストに含まれるコールの CU 重み付けの合計が、そのキーのバースト容量(burst_cu)を超えると、リクエストは拒否され、HTTP 429 -32022 request cost <N> CU exceeds burst capacity <M> CU が返されます(課金対象外)。より小さなバッチに分割してください。
  • バケット容量の不足:重み付けの全額の合計がバースト容量を超えていなくても、トークンバケットの利用可能な容量が不足している場合、サービスは HTTP 429 とエラーコード -32005 rate limit exceeded、Retry-After を返します。再試行と課金の詳細は、課金対象外のもの:エラーコードと課金ルールを参照してください。

そのため、大規模なログクエリでは、分割したクエリを順番に実行する方法を推奨します。バッチ化する場合は、重み付けの全額の合計がバースト容量内に収まるよう、各バッチのコール数を十分に少なくしてください。

関連ガイドと課金ルール

次のステップ

最終更新:

このページの目次