[Bug] eth_call Errors Cause Infinite Loop in Local and Remote Graph Node

オープン
#5,622 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
35/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
停滞
技術スタック
rust, typescript

調査の方向性

Graph Node の eth_call のリトライ処理と、レポートに示されている SubgraphInstanceManager のログから始めてください。提供された do-while の例と記録された VM 実行エラーを使って失敗を再現してください。eth_call の失敗が無限にリトライされずに処理され、インデックス作成を継続できれば完了です。

索引モデルが issue の本文から書いたものです。

説明

bug Stale
Bug report

Description:
I’m facing an issue while developing a subgraph locally and on a remote Graph Node. When my handler function executes an eth_call and encounters an error like "VM execution error", the indexing process gets stuck. Instead of moving forward, the node repeatedly sends the same eth_call request, encountering the same error over and over, resulting in an infinite loop.

Expected Behavior:
When an eth_call results in an error, such as "VM execution error", the Graph Node should handle the error gracefully by logging it and then continuing with the indexing process, avoiding getting stuck in a loop.

Actual Behavior:
The Graph Node enters an infinite loop, where it keeps retrying the same eth_call that causes the "VM execution error". This halts the indexing process, preventing any further progress.

Code Example:

// Function to get swap info from a contract
export function getSwapInfoNoWithdrawFee(swap: Address): SwapInfo {
  let swapContract = SwapFlashLoanNoWithdrawFee.bind(swap)

  let tokens: Address[] = []
  let balances: BigInt[] = []

  let t: ethereum.CallResult<Address>
  let b: ethereum.CallResult<BigInt>

  let i = 0

  // Loop through token indices to get token addresses and balances
  do {
    t = swapContract.try_getToken(i)
    b = swapContract.try_getTokenBalance(i)

    if (!t.reverted && t.value.toHexString() != ZERO_ADDRESS) {
      tokens.push(t.value)
    }

    if (!b.reverted) {
      balances.push(b.value)
    }

    i++
  } while (!t.reverted && !b.reverted)

  // Get additional swap info
  let lpTokenSupply = getTotalSupply(swap)

  return {
    tokens,
    balances,
    A: swapContract.getA(),
    swapFee: swapContract.swapStorage().value4,
    adminFee: swapContract.swapStorage().value5,
    withdrawFee: BigInt.fromI32(0),
    virtualPrice: swapContract.getVirtualPrice(),
    owner: swapContract.owner(),
    lpToken: swapContract.swapStorage().value6,
    lpTokenSupply,
  }
}

Problem Details:
The issue occurs in the do-while loop, where the function iterates through token indices to retrieve token addresses and balances using the try_getToken and try_getTokenBalance methods.

When the contract returns an error (e.g., "VM execution error" or "Reverted Out of range"), the loop should ideally stop or handle the error gracefully. However, instead, the Graph Node enters an infinite loop, continually retrying the same eth_call, causing the node to get stuck and preventing it from continuing the indexing process.

Steps to Reproduce:

  1. Deploy a subgraph that includes a handler function making an eth_call to a contract.
  2. Trigger an eth_call failure (e.g., by passing an out-of-range value or an invalid token index).
  3. Observe the behavior of the Graph Node as it repeatedly retries the eth_call and logs the same error.

Logs:

ERRO Ethereum node returned an error when calling function "getToken" of contract "SwapFlashLoanNoWithdrawFee": RPC error: Error { code: ServerError(-32015), message: "VM execution error.", data: Some(String("Reverted Out of range")) }, sgd: 1, subgraph_id: QmZSSowKwzADwD6wpXx7DBEkkKYBFmKG7VNZtcqB3HXmsk, component: SubgraphInstanceManager

WARN Trying again after eth_call RPC call for block #16199484 (bab0ef7134d84a23819c8c1305c061e8e23858f3a78759efbcc7f5889798ee95) failed (attempt #10) with result Err(Web3Error(Rpc(Error { code: ServerError(-32015), message: "VM execution error.", data: Some(String("Reverted Out of range")) }))), provider: fuse-rpc-0, sgd: 1, subgraph_id: QmZSSowKwzADwD6wpXx7DBEkkKYBFmKG7VNZtcqB3HXmsk, component: SubgraphInstanceManager

Additional Information:
Interestingly, when I deploy the same subgraph to the hosted Graph Node on Graph Studio, the error is handled differently. Although the same eth_call error occurs, the indexing process continues without issues. It seems the hosted service has additional error-handling mechanisms that are not present in the local or remote Graph Node setup.

Proposed Solution:
It would be beneficial if the local and remote Graph Node instances could implement similar error-handling behavior as the hosted Graph Node on Graph Studio. Specifically, the node should be able to catch these eth_call errors and continue indexing without getting stuck in an infinite loop.

Steps to Resolve:

  1. Introduce a mechanism to handle specific eth_call errors, such as logging the error and skipping the problematic block or transaction.
  2. Optionally, provide configuration options to control the retry behavior or to handle specific error codes in a customizable way.
Relevant log output

No response

IPFS hash

No response

Subgraph name or link to explorer

No response

Some information to help us out
  • Tick this box if this bug is caused by a regression found in the latest release.
  • Tick this box if this bug is specific to the hosted service.
  • I have searched the issue tracker to make sure this issue is not a duplicate.
OS information

None

主要言語
Rust
スター
3.2k
フォーク
1.1k
平均マージ
4日 1時間
マージ済み PR(30日)
1

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

graphprotocol/graph-node のほかの issue

graphprotocol/graph-node の issue をすべて見る

似ている issue

Rust の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。