diff --git a/eth/tracers/api.go b/eth/tracers/api.go index c6941eea8e..5eac53f19a 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -80,6 +80,8 @@ type Backend interface { // so this method should be called with the parent. StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive, preferDisk bool) (*state.StateDB, error) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error) + + HistoricalRPCService() *rpc.Client } // API is the collection of tracing APIs exposed over the private debugging endpoint. diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index 1541ca192e..d0d6ace6ad 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -24,11 +24,16 @@ import ( "errors" "fmt" "math/big" + "net" + "net/http" "reflect" "sort" "testing" "time" + "github.com/ethereum/go-ethereum/node" + + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus" @@ -52,18 +57,68 @@ var ( errTransactionNotFound = errors.New("transaction not found") ) +type mockHistoricalBackend struct{} + +func (m *mockHistoricalBackend) Dummy() { + +} + +func newMockHistoricalBackend(t *testing.T) string { + s := rpc.NewServer() + err := node.RegisterApis([]rpc.API{ + { + Namespace: "eth", + Service: new(mockHistoricalBackend), + Public: true, + Authenticated: false, + }, + }, nil, s) + if err != nil { + t.Fatalf("error creating mock historical backend: %v", err) + } + + hdlr := node.NewHTTPHandlerStack(s, []string{"*"}, []string{"*"}, nil) + mux := http.NewServeMux() + mux.Handle("/", hdlr) + + listener, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + t.Fatalf("error creating mock historical backend listener: %v", err) + } + + go func() { + httpS := &http.Server{Handler: mux} + httpS.Serve(listener) + + t.Cleanup(func() { + httpS.Shutdown(context.Background()) + }) + }() + + return fmt.Sprintf("http://%s", listener.Addr().String()) +} + type testBackend struct { chainConfig *params.ChainConfig engine consensus.Engine chaindb ethdb.Database chain *core.BlockChain + historical *rpc.Client } func newTestBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i int, b *core.BlockGen)) *testBackend { + historicalAddr := newMockHistoricalBackend(t) + + historicalClient, err := rpc.Dial(historicalAddr) + if err != nil { + t.Fatalf("error making historical client: %v", err) + } + backend := &testBackend{ chainConfig: params.TestChainConfig, engine: ethash.NewFaker(), chaindb: rawdb.NewMemoryDatabase(), + historical: historicalClient, } // Generate blocks for testing gspec.Config = backend.chainConfig @@ -178,6 +233,10 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash()) } +func (b *testBackend) HistoricalRPCService() *rpc.Client { + return b.historical +} + func TestTraceCall(t *testing.T) { t.Parallel() @@ -240,7 +299,7 @@ func TestTraceCall(t *testing.T) { Value: (*hexutil.Big)(big.NewInt(1000)), }, config: nil, - expectErr: fmt.Errorf("block #%d not found", genBlocks+1), + expectErr: fmt.Errorf("block #%d %w", genBlocks+1, ethereum.NotFound), //expect: nil, }, // Standard JSON trace upon the latest block @@ -288,7 +347,7 @@ func TestTraceCall(t *testing.T) { t.Errorf("test %d: expect error %v, got nothing", i, testspec.expectErr) continue } - if !reflect.DeepEqual(err, testspec.expectErr) { + if err.Error() != testspec.expectErr.Error() { t.Errorf("test %d: error mismatch, want %v, git %v", i, testspec.expectErr, err) } } else { @@ -393,7 +452,7 @@ func TestTraceBlock(t *testing.T) { // Trace non-existent block { blockNumber: rpc.BlockNumber(genBlocks + 1), - expectErr: fmt.Errorf("block #%d not found", genBlocks+1), + expectErr: fmt.Errorf("block #%d %w", genBlocks+1, ethereum.NotFound), }, // Trace latest block { @@ -413,7 +472,7 @@ func TestTraceBlock(t *testing.T) { t.Errorf("test %d, want error %v", i, tc.expectErr) continue } - if !reflect.DeepEqual(err, tc.expectErr) { + if err.Error() != tc.expectErr.Error() { t.Errorf("test %d: error mismatch, want %v, get %v", i, tc.expectErr, err) } continue diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 041c701041..33e1ad7660 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -49,6 +49,8 @@ import ( "github.com/tyler-smith/go-bip39" ) +var ErrHeaderNotFound = fmt.Errorf("header %w", ethereum.NotFound) + // EthereumAPI provides an API to access Ethereum related information. type EthereumAPI struct { b Backend