You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

go-ethereum中client.BlockByHash()调用报'not found'错误求助

解决以太坊订阅新区块后通过哈希获取区块失败的问题

问题根源

当通过SubscribeNewHead接收到新区块头时,对应的完整区块数据可能还未完全同步到Infura节点的存储中,此时立刻调用BlockByHash会触发"not found"错误。而区块头的哈希能正常输出,仅说明WebSocket连接正常且收到了新区块头的广播,不代表完整区块已就绪。

解决方案

方案1:直接使用区块头获取基础信息(推荐)

如果仅需要区块号、时间、nonce这类基础字段,完全不需要额外请求完整区块——订阅返回的*types.Header对象已经包含这些数据,既避免错误又提升性能:

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/ethereum/go-ethereum/core/types"
    "github.com/ethereum/go-ethereum/ethclient"
)

func main() {
    client, err := ethclient.Dial("wss://mainnet.infura.io/ws/v3/APIKEY")
    if err != nil {
        log.Fatal(err)
    }

    headers := make(chan *types.Header)
    sub, err := client.SubscribeNewHead(context.Background(), headers)
    if err != nil {
        log.Fatal(err)
    }

    for {
        select {
        case err := <-sub.Err():
            log.Fatal(err)
        case header := <-headers:
            fmt.Println(header.Hash().Hex())    // 区块哈希
            fmt.Println(header.Number.Uint64()) // 区块号
            fmt.Println(header.Time)            // 区块时间
            fmt.Println(header.Nonce)           // Nonce
            // 注意:区块头不包含交易列表,若需交易必须请求完整区块
        }
    }
}

方案2:需要完整区块时添加重试逻辑

如果必须获取包含交易的完整区块,可通过重试机制等待区块数据同步完成:

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/ethereum/go-ethereum/core/types"
    "github.com/ethereum/go-ethereum/ethclient"
)

func main() {
    client, err := ethclient.Dial("wss://mainnet.infura.io/ws/v3/APIKEY")
    if err != nil {
        log.Fatal(err)
    }

    headers := make(chan *types.Header)
    sub, err := client.SubscribeNewHead(context.Background(), headers)
    if err != nil {
        log.Fatal(err)
    }

    for {
        select {
        case err := <-sub.Err():
            log.Fatal(err)
        case header := <-headers:
            fmt.Println(header.Hash().Hex())
            
            // 重试获取完整区块,最多尝试5次,每次间隔1秒
            var block *types.Block
            retryCount := 0
            maxRetries := 5
            for retryCount < maxRetries {
                block, err = client.BlockByHash(context.Background(), header.Hash())
                if err == nil {
                    break
                }
                retryCount++
                time.Sleep(1 * time.Second)
                log.Printf("重试获取区块,次数:%d", retryCount)
            }
            
            if err != nil {
                log.Printf("多次重试后仍无法获取区块:%v", err)
                continue
            }

            fmt.Println(block.Hash().Hex())        // 区块哈希
            fmt.Println(block.Number().Uint64())   // 区块号
            fmt.Println(block.Time())              // 区块时间
            fmt.Println(block.Nonce())             // Nonce
            fmt.Println(len(block.Transactions())) // 交易数量
        }
    }
}

额外提示

  • 替换代码中的APIKEY为你自己的Infura API密钥。
  • 优先使用方案1,减少不必要的RPC请求能降低Infura调用频率限制风险,同时提升程序响应速度。

内容的提问来源于stack exchange,提问作者Filipe Aleixo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 11:52:50