diff --git a/pkg/debug/api.go b/pkg/debug/api.go
deleted file mode 100644
index 69ae807d..00000000
--- a/pkg/debug/api.go
+++ /dev/null
@@ -1,194 +0,0 @@
-// VulcanizeDB
-// Copyright © 2022 Vulcanize
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package debug
-
-import (
- "context"
- "errors"
- "fmt"
- "time"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/state"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/core/vm"
- "github.com/ethereum/go-ethereum/eth/tracers"
- "github.com/ethereum/go-ethereum/eth/tracers/logger"
- "github.com/ethereum/go-ethereum/rpc"
-
- "github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
-)
-
-const (
- // defaultTraceTimeout is the amount of time a single transaction can execute
- // by default before being forcefully aborted.
- defaultTraceTimeout = 30 * time.Second
-)
-
-// TraceCallConfig is the config for traceCall API. It holds one more
-// field to override the state for tracing.
-type TraceCallConfig struct {
- tracers.TraceConfig
- StateOverrides *eth.StateOverride
-}
-
-// APIName is the namespace for the watcher's debug api
-const APIName = "debug"
-
-// APIVersion is the version of the watcher's debug api
-const APIVersion = "0.0.1"
-
-type DebugAPI struct {
- // Local db backend
- B *eth.Backend
-}
-
-// NewAPI creates a new API definition for the tracing methods of the Ethereum service.
-func NewDebugAPI(backend *eth.Backend) *DebugAPI {
- return &DebugAPI{B: backend}
-}
-
-// blockByNumber is the wrapper of the chain access function offered by the backend.
-// It will return an error if the block is not found.
-func (api *DebugAPI) blockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
- block, err := api.B.BlockByNumber(ctx, number)
- if err != nil {
- return nil, err
- }
- if block == nil {
- return nil, fmt.Errorf("block #%d not found", number)
- }
- return block, nil
-}
-
-// blockByHash is the wrapper of the chain access function offered by the backend.
-// It will return an error if the block is not found.
-func (api *DebugAPI) blockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
- block, err := api.B.BlockByHash(ctx, hash)
- if err != nil {
- return nil, err
- }
- if block == nil {
- return nil, fmt.Errorf("block %s not found", hash.Hex())
- }
- return block, nil
-}
-
-// TODO: use API implementation from geth directly
-// TraceCall lets you trace a given eth_call. It collects the structured logs
-// created during the execution of EVM if the given transaction was added on
-// top of the provided block and returns them as a JSON object.
-func (api *DebugAPI) TraceCall(ctx context.Context, args eth.CallArgs, blockNrOrHash rpc.BlockNumberOrHash, config *TraceCallConfig) (interface{}, error) {
- // Try to retrieve the specified block
- var (
- err error
- block *types.Block
- )
- if hash, ok := blockNrOrHash.Hash(); ok {
- block, err = api.blockByHash(ctx, hash)
- } else if number, ok := blockNrOrHash.Number(); ok {
- if number == rpc.PendingBlockNumber {
- // We don't have access to the miner here. For tracing 'future' transactions,
- // it can be done with block- and state-overrides instead, which offers
- // more flexibility and stability than trying to trace on 'pending', since
- // the contents of 'pending' is unstable and probably not a true representation
- // of what the next actual block is likely to contain.
- return nil, errors.New("tracing on top of pending is not supported")
- }
- block, err = api.blockByNumber(ctx, number)
- } else {
- return nil, errors.New("invalid arguments; neither block nor hash specified")
- }
- if err != nil {
- return nil, err
- }
-
- statedb, _, err := api.B.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
- if err != nil {
- return nil, err
- }
- vmctx := core.NewEVMBlockContext(block.Header(), api.B, nil)
- // Apply the customization rules if required.
- if config != nil {
- if err := config.StateOverrides.Apply(statedb); err != nil {
- return nil, err
- }
- }
- // Execute the trace
- msg, err := args.ToMessage(api.B.Config.RPCGasCap.Uint64(), block.BaseFee())
- if err != nil {
- return nil, err
- }
-
- var traceConfig *tracers.TraceConfig
- if config != nil {
- traceConfig = &tracers.TraceConfig{
- Config: config.Config,
- Tracer: config.Tracer,
- Timeout: config.Timeout,
- Reexec: config.Reexec,
- }
- }
- return api.traceTx(ctx, msg, new(tracers.Context), vmctx, statedb, traceConfig)
-}
-
-// traceTx configures a new tracer according to the provided configuration, and
-// executes the given message in the provided environment. The return value will
-// be tracer dependent.
-func (api *DebugAPI) traceTx(ctx context.Context, message core.Message, txctx *tracers.Context, vmctx vm.BlockContext, statedb *state.StateDB, config *tracers.TraceConfig) (interface{}, error) {
- var (
- tracer tracers.Tracer
- err error
- timeout = defaultTraceTimeout
- txContext = core.NewEVMTxContext(message)
- )
- if config == nil {
- config = &tracers.TraceConfig{}
- }
- // Default tracer is the struct logger
- tracer = logger.NewStructLogger(config.Config)
- if config.Tracer != nil {
- tracer, err = tracers.New(*config.Tracer, txctx, config.TracerConfig)
- if err != nil {
- return nil, err
- }
- }
- // Define a meaningful timeout of a single transaction trace
- if config.Timeout != nil {
- if timeout, err = time.ParseDuration(*config.Timeout); err != nil {
- return nil, err
- }
- }
- deadlineCtx, cancel := context.WithTimeout(ctx, timeout)
- go func() {
- <-deadlineCtx.Done()
- if errors.Is(deadlineCtx.Err(), context.DeadlineExceeded) {
- tracer.Stop(errors.New("execution timeout"))
- }
- }()
- defer cancel()
-
- // Run the transaction with tracing enabled.
- vmenv := vm.NewEVM(vmctx, txContext, statedb, api.B.Config.ChainConfig, vm.Config{Debug: true, Tracer: tracer, NoBaseFee: true})
- // Call Prepare to clear out the statedb access list
- statedb.Prepare(txctx.TxHash, txctx.TxIndex)
- if _, err = core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas())); err != nil {
- return nil, fmt.Errorf("tracing failed: %w", err)
- }
- return tracer.GetResult()
-}
diff --git a/pkg/debug/backend.go b/pkg/debug/backend.go
new file mode 100644
index 00000000..bf4a1b40
--- /dev/null
+++ b/pkg/debug/backend.go
@@ -0,0 +1,54 @@
+// VulcanizeDB
+// Copyright © 2022 Vulcanize
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package debug
+
+import (
+ "context"
+ "errors"
+
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/eth/tracers"
+ "github.com/ethereum/go-ethereum/rpc"
+
+ "github.com/cerc-io/ipld-eth-server/v4/pkg/eth"
+)
+
+var _ tracers.Backend = &Backend{}
+
+var (
+ errMethodNotSupported = errors.New("backend method not supported")
+)
+
+// Backend implements tracers.Backend interface
+type Backend struct {
+ eth.Backend
+}
+
+// StateAtBlock retrieves the state database associated with a certain block
+func (b *Backend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive, preferDisk bool) (*state.StateDB, error) {
+ rpcBlockNumber := rpc.BlockNumber(block.NumberU64())
+ statedb, _, err := b.StateAndHeaderByNumberOrHash(ctx, rpc.BlockNumberOrHashWithNumber(rpcBlockNumber))
+ return statedb, err
+}
+
+// StateAtTransaction returns the execution environment of a certain transaction
+func (b *Backend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error) {
+ return nil, vm.BlockContext{}, nil, errMethodNotSupported
+}
diff --git a/pkg/eth/backend.go b/pkg/eth/backend.go
index 0a1d9517..7e55877c 100644
--- a/pkg/eth/backend.go
+++ b/pkg/eth/backend.go
@@ -258,6 +258,11 @@ func (b *Backend) GetTd(blockHash common.Hash) (*big.Int, error) {
return td, nil
}
+// ChainConfig returns the active chain configuration.
+func (b *Backend) ChainConfig() *params.ChainConfig {
+ return b.Config.ChainConfig
+}
+
// CurrentBlock returns the current block
func (b *Backend) CurrentBlock() (*types.Block, error) {
block, err := b.BlockByNumber(context.Background(), rpc.LatestBlockNumber)
@@ -849,8 +854,8 @@ func (b *Backend) ValidateTrie(stateRoot common.Hash) error {
}
// RPCGasCap returns the configured gas cap for the rpc server
-func (b *Backend) RPCGasCap() *big.Int {
- return b.Config.RPCGasCap
+func (b *Backend) RPCGasCap() uint64 {
+ return b.Config.RPCGasCap.Uint64()
}
func (b *Backend) SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription {
diff --git a/pkg/graphql/graphql.go b/pkg/graphql/graphql.go
index 9047839d..b4dc9ffe 100644
--- a/pkg/graphql/graphql.go
+++ b/pkg/graphql/graphql.go
@@ -838,7 +838,7 @@ func (b *Block) Call(ctx context.Context, args struct {
return nil, err
}
}
- result, err := eth.DoCall(ctx, b.backend, args.Data, *b.numberOrHash, nil, 5*time.Second, b.backend.RPCGasCap().Uint64())
+ result, err := eth.DoCall(ctx, b.backend, args.Data, *b.numberOrHash, nil, 5*time.Second, b.backend.RPCGasCap())
if err != nil {
return nil, err
}
diff --git a/pkg/rpc/ipc.go b/pkg/rpc/ipc.go
index e18fe4af..5a09f5af 100644
--- a/pkg/rpc/ipc.go
+++ b/pkg/rpc/ipc.go
@@ -25,6 +25,7 @@ import (
"github.com/ethereum/go-ethereum/p2p/netutil"
"github.com/ethereum/go-ethereum/rpc"
log "github.com/sirupsen/logrus"
+
"github.com/cerc-io/ipld-eth-server/v4/pkg/prom"
)
diff --git a/pkg/serve/service.go b/pkg/serve/service.go
index ab56bc36..297b7183 100644
--- a/pkg/serve/service.go
+++ b/pkg/serve/service.go
@@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/eth/tracers"
ethnode "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rlp"
@@ -139,22 +140,24 @@ func (sap *Service) APIs() []rpc.API {
Service: net.NewPublicNetAPI(networkID, sap.client),
Public: true,
},
- {
- Namespace: debug.APIName,
- Version: debug.APIVersion,
- Service: debug.NewDebugAPI(sap.backend),
- },
}
+
ethAPI, err := eth.NewPublicEthAPI(sap.backend, sap.client, sap.supportsStateDiffing, sap.forwardEthCalls, sap.proxyOnError)
if err != nil {
log.Fatalf("unable to create public eth api: %v", err)
}
- return append(apis, rpc.API{
- Namespace: eth.APIName,
- Version: eth.APIVersion,
- Service: ethAPI,
- Public: true,
- })
+
+ debugTracerAPI := tracers.APIs(&debug.Backend{Backend: *sap.backend})[0]
+
+ return append(apis,
+ rpc.API{
+ Namespace: eth.APIName,
+ Version: eth.APIVersion,
+ Service: ethAPI,
+ Public: true,
+ },
+ debugTracerAPI,
+ )
}
// Serve listens for incoming converter data off the screenAndServePayload from the Sync process
diff --git a/test/watch_address_integration_test.go b/test/watch_address_integration_test.go
index ffa00aee..0ee334b7 100644
--- a/test/watch_address_integration_test.go
+++ b/test/watch_address_integration_test.go
@@ -13,6 +13,7 @@ import (
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
+
integration "github.com/cerc-io/ipld-eth-server/v4/test"
)