From 95f91c91ff5ed885c52b57fb822db20ad7841915 Mon Sep 17 00:00:00 2001 From: Bilog WEB3 <155262265+Bilogweb3@users.noreply.github.com> Date: Fri, 14 Nov 2025 10:49:35 +0100 Subject: [PATCH 1/2] ethclient: preserve requireCanonical in BlockReceipts --- ethclient/ethclient.go | 2 +- ethclient/ethclient_test.go | 42 +++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 5008378da6a..aeb0db11ed4 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -124,7 +124,7 @@ func (ec *Client) PeerCount(ctx context.Context) (uint64, error) { // BlockReceipts returns the receipts of a given block number or hash. func (ec *Client) BlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]*types.Receipt, error) { var r []*types.Receipt - err := ec.c.CallContext(ctx, &r, "eth_getBlockReceipts", blockNrOrHash.String()) + err := ec.c.CallContext(ctx, &r, "eth_getBlockReceipts", blockNrOrHash) if err == nil && r == nil { return nil, ethereum.NotFound } diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go index 302ccf2e16c..7d71994c791 100644 --- a/ethclient/ethclient_test.go +++ b/ethclient/ethclient_test.go @@ -1001,3 +1001,45 @@ func TestSimulateV1WithBlockNumberOrHash(t *testing.T) { t.Fatalf("expected 1 block result, got %d", len(results)) } } + +func TestBlockReceiptsPreservesRequireCanonical(t *testing.T) { + server := rpc.NewServer() + service := &testBlockReceiptsService{} + if err := server.RegisterName("eth", service); err != nil { + t.Fatalf("failed to register test service: %v", err) + } + defer server.Stop() + + rpcClient := rpc.DialInProc(server) + defer rpcClient.Close() + + client := ethclient.NewClient(rpcClient) + defer client.Close() + + hash := common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111") + arg := rpc.BlockNumberOrHashWithHash(hash, true) + + if _, err := client.BlockReceipts(context.Background(), arg); err != nil { + t.Fatalf("BlockReceipts returned error: %v", err) + } + if !service.called { + t.Fatalf("expected GetBlockReceipts to be called") + } + if !service.lastArg.RequireCanonical { + t.Fatalf("requireCanonical flag was not preserved") + } + if service.lastArg.BlockHash == nil || *service.lastArg.BlockHash != hash { + t.Fatalf("unexpected block hash: %v", service.lastArg.BlockHash) + } +} + +type testBlockReceiptsService struct { + lastArg rpc.BlockNumberOrHash + called bool +} + +func (s *testBlockReceiptsService) GetBlockReceipts(ctx context.Context, arg rpc.BlockNumberOrHash) ([]*types.Receipt, error) { + s.lastArg = arg + s.called = true + return []*types.Receipt{}, nil +} From b9567746349c4ea13d0a40be201b87d3d03899bb Mon Sep 17 00:00:00 2001 From: Bilog WEB3 <155262265+Bilogweb3@users.noreply.github.com> Date: Mon, 17 Nov 2025 15:48:20 +0000 Subject: [PATCH 2/2] gethclient: preserve requireCanonical in BlockReceipts --- ethclient/ethclient.go | 2 +- ethclient/ethclient_test.go | 42 ------------------------- ethclient/gethclient/gethclient.go | 11 +++++++ ethclient/gethclient/gethclient_test.go | 41 ++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 43 deletions(-) diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index aeb0db11ed4..5008378da6a 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -124,7 +124,7 @@ func (ec *Client) PeerCount(ctx context.Context) (uint64, error) { // BlockReceipts returns the receipts of a given block number or hash. func (ec *Client) BlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]*types.Receipt, error) { var r []*types.Receipt - err := ec.c.CallContext(ctx, &r, "eth_getBlockReceipts", blockNrOrHash) + err := ec.c.CallContext(ctx, &r, "eth_getBlockReceipts", blockNrOrHash.String()) if err == nil && r == nil { return nil, ethereum.NotFound } diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go index 7d71994c791..302ccf2e16c 100644 --- a/ethclient/ethclient_test.go +++ b/ethclient/ethclient_test.go @@ -1001,45 +1001,3 @@ func TestSimulateV1WithBlockNumberOrHash(t *testing.T) { t.Fatalf("expected 1 block result, got %d", len(results)) } } - -func TestBlockReceiptsPreservesRequireCanonical(t *testing.T) { - server := rpc.NewServer() - service := &testBlockReceiptsService{} - if err := server.RegisterName("eth", service); err != nil { - t.Fatalf("failed to register test service: %v", err) - } - defer server.Stop() - - rpcClient := rpc.DialInProc(server) - defer rpcClient.Close() - - client := ethclient.NewClient(rpcClient) - defer client.Close() - - hash := common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111") - arg := rpc.BlockNumberOrHashWithHash(hash, true) - - if _, err := client.BlockReceipts(context.Background(), arg); err != nil { - t.Fatalf("BlockReceipts returned error: %v", err) - } - if !service.called { - t.Fatalf("expected GetBlockReceipts to be called") - } - if !service.lastArg.RequireCanonical { - t.Fatalf("requireCanonical flag was not preserved") - } - if service.lastArg.BlockHash == nil || *service.lastArg.BlockHash != hash { - t.Fatalf("unexpected block hash: %v", service.lastArg.BlockHash) - } -} - -type testBlockReceiptsService struct { - lastArg rpc.BlockNumberOrHash - called bool -} - -func (s *testBlockReceiptsService) GetBlockReceipts(ctx context.Context, arg rpc.BlockNumberOrHash) ([]*types.Receipt, error) { - s.lastArg = arg - s.called = true - return []*types.Receipt{}, nil -} diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go index 6a0f5eb3123..9c732ea4739 100644 --- a/ethclient/gethclient/gethclient.go +++ b/ethclient/gethclient/gethclient.go @@ -166,6 +166,17 @@ func (ec *Client) CallContractWithBlockOverrides(ctx context.Context, msg ethere return hex, err } +// BlockReceipts returns the receipts of a given block number or hash. +// This wrapper preserves geth-specific flags such as requireCanonical. +func (ec *Client) BlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]*types.Receipt, error) { + var r []*types.Receipt + err := ec.c.CallContext(ctx, &r, "eth_getBlockReceipts", blockNrOrHash) + if err == nil && r == nil { + return nil, ethereum.NotFound + } + return r, err +} + // GCStats retrieves the current garbage collection stats from a geth node. func (ec *Client) GCStats(ctx context.Context) (*debug.GCStats, error) { var result debug.GCStats diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index 0eed63cacfe..47a5cd312fd 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -620,3 +620,44 @@ func testCallContractWithBlockOverrides(t *testing.T, client *rpc.Client) { t.Fatalf("unexpected result: %x", res) } } + +func TestGethClientBlockReceiptsPreservesRequireCanonical(t *testing.T) { + server := rpc.NewServer() + service := &testGethBlockReceiptsService{} + if err := server.RegisterName("eth", service); err != nil { + t.Fatalf("failed to register test service: %v", err) + } + defer server.Stop() + + rpcClient := rpc.DialInProc(server) + defer rpcClient.Close() + + client := New(rpcClient) + + hash := common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111") + arg := rpc.BlockNumberOrHashWithHash(hash, true) + + if _, err := client.BlockReceipts(context.Background(), arg); err != nil { + t.Fatalf("BlockReceipts returned error: %v", err) + } + if !service.called { + t.Fatalf("expected GetBlockReceipts to be called") + } + if !service.lastArg.RequireCanonical { + t.Fatalf("requireCanonical flag was not preserved") + } + if service.lastArg.BlockHash == nil || *service.lastArg.BlockHash != hash { + t.Fatalf("unexpected block hash: %v", service.lastArg.BlockHash) + } +} + +type testGethBlockReceiptsService struct { + lastArg rpc.BlockNumberOrHash + called bool +} + +func (s *testGethBlockReceiptsService) GetBlockReceipts(ctx context.Context, arg rpc.BlockNumberOrHash) ([]*types.Receipt, error) { + s.lastArg = arg + s.called = true + return []*types.Receipt{}, nil +}