diff --git a/pkg/debug/backend.go b/pkg/debug/backend.go index 258d1708..12cacf67 100644 --- a/pkg/debug/backend.go +++ b/pkg/debug/backend.go @@ -42,14 +42,13 @@ type Backend struct { } // StateAtBlock retrieves the state database associated with a certain block -// We can't sub in our ipld-eth-statedb here because to match the expected interface we need to return *state.StateDB not vm.StateDB -func (b *Backend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive, preferDisk bool) (*state.StateDB, error) { +func (b *Backend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive, preferDisk bool) (*state.StateDB, tracers.StateReleaseFunc, error) { rpcBlockNumber := rpc.BlockNumber(block.NumberU64()) statedb, _, err := b.StateAndHeaderByNumberOrHash(ctx, rpc.BlockNumberOrHashWithNumber(rpcBlockNumber)) - return statedb, err + return statedb, func() {}, 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 +func (b *Backend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { + return nil, vm.BlockContext{}, nil, func() {}, errMethodNotSupported } diff --git a/pkg/eth/api.go b/pkg/eth/api.go index fa932e48..120ede1d 100644 --- a/pkg/eth/api.go +++ b/pkg/eth/api.go @@ -510,7 +510,7 @@ type feeHistoryResult struct { } // FeeHistory returns the fee market history. -func (pea *PublicEthAPI) FeeHistory(ctx context.Context, blockCount rpc.DecimalOrHex, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*feeHistoryResult, error) { +func (pea *PublicEthAPI) FeeHistory(ctx context.Context, blockCount int, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*feeHistoryResult, error) { if pea.rpc != nil { var res *feeHistoryResult if err := pea.rpc.CallContext(ctx, &res, "eth_feeHistory", blockCount, lastBlock, rewardPercentiles); err != nil { @@ -596,7 +596,7 @@ func (pea *PublicEthAPI) localGetTransactionReceipt(ctx context.Context, hash co if err != nil { return nil, err } - err = receipts.DeriveFields(pea.B.Config.ChainConfig, blockHash, blockNumber, block.Transactions()) + err = receipts.DeriveFields(pea.B.Config.ChainConfig, blockHash, blockNumber, block.BaseFee(), block.Transactions()) if err != nil { return nil, err } @@ -882,7 +882,10 @@ func (pea *PublicEthAPI) localGetProof(ctx context.Context, address common.Addre return nil, err } - storageTrie := state.StorageTrie(address) + storageTrie, err := state.StorageTrie(address) + if storageTrie == nil || err != nil { + return nil, err + } storageHash := types.EmptyRootHash codeHash := state.GetCodeHash(address) storageProof := make([]StorageResult, len(storageKeys)) @@ -1106,7 +1109,7 @@ func DoCall(ctx context.Context, b *Backend, args CallArgs, blockNrOrHash rpc.Bl return nil, fmt.Errorf("execution aborted (timeout = %v)", timeout) } if err != nil { - return result, fmt.Errorf("err: %w (supplied gas %d)", err, msg.Gas()) + return result, fmt.Errorf("err: %w (supplied gas %d)", err, args.Gas) } return result, nil } diff --git a/pkg/eth/backend.go b/pkg/eth/backend.go index 11c79342..bb571343 100644 --- a/pkg/eth/backend.go +++ b/pkg/eth/backend.go @@ -374,6 +374,27 @@ func (b *Backend) GetHeaderByBlockHash(tx *sqlx.Tx, hash common.Hash) (*types.He return header, rlp.DecodeBytes(headerRLP, header) } +// CurrentHeader returns the current block's header +func (b *Backend) CurrentHeader() *types.Header { + block, err := b.BlockByNumber(context.Background(), rpc.LatestBlockNumber) + if err != nil { + return nil + } + return block.Header() +} + +// GetBody returns the the body for the provided block hash and number +func (b *Backend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) { + if number < 0 || hash == (common.Hash{}) { + return nil, errors.New("invalid arguments; expect hash and no special block numbers") + } + block, bErr := b.BlockByHash(ctx, hash) + if block != nil && bErr == nil { + return block.Body(), nil + } + return nil, errors.New("block body not found") +} + // GetUnclesByBlockHash retrieves uncles for a provided block hash func (b *Backend) GetUnclesByBlockHash(tx *sqlx.Tx, hash common.Hash) ([]*types.Header, error) { _, uncleBytes, err := b.Retriever.RetrieveUnclesByBlockHash(tx, hash) @@ -682,11 +703,11 @@ func (b *Backend) GetCanonicalHeader(number uint64) (string, []byte, error) { } // GetEVM constructs and returns a vm.EVM -func (b *Backend) GetEVM(ctx context.Context, msg core.Message, state vm.StateDB, header *types.Header) (*vm.EVM, func() error, error) { +func (b *Backend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) { vmError := func() error { return nil } txContext := core.NewEVMTxContext(msg) - blockContext := core.NewEVMBlockContext(header, b, nil) - return vm.NewEVM(blockContext, txContext, state, b.Config.ChainConfig, b.Config.VMConfig), vmError, nil + evmCtx := core.NewEVMBlockContext(header, b, nil) + return vm.NewEVM(evmCtx, txContext, state, b.Config.ChainConfig, b.Config.VMConfig), vmError, nil } // GetAccountByNumberOrHash returns the account object for the provided address at the block corresponding to the provided number or hash diff --git a/pkg/eth/test_helpers/chain_maker.go b/pkg/eth/test_helpers/chain_maker.go index a3a7369d..b4f893d6 100644 --- a/pkg/eth/test_helpers/chain_maker.go +++ b/pkg/eth/test_helpers/chain_maker.go @@ -69,7 +69,7 @@ func MakeChain(n int, parent *types.Block, chainGen func(int, *core.BlockGen)) ( config := params.TestChainConfig config.LondonBlock = big.NewInt(100) blocks, receipts := core.GenerateChain(config, parent, ethash.NewFaker(), Testdb, n, chainGen) - chain, _ := core.NewBlockChain(Testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil) + chain, _ := core.NewBlockChain(Testdb, nil, nil, nil, ethash.NewFaker(), vm.Config{}, nil, nil) return append([]*types.Block{parent}, blocks...), receipts, chain } diff --git a/pkg/eth/types.go b/pkg/eth/types.go index c74c959c..d9ce73f3 100644 --- a/pkg/eth/types.go +++ b/pkg/eth/types.go @@ -22,6 +22,8 @@ import ( "math/big" "strconv" + "github.com/ethereum/go-ethereum/core" + "github.com/cerc-io/ipld-eth-server/v4/pkg/log" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -125,10 +127,10 @@ func (arg *CallArgs) data() []byte { // ToMessage converts the transaction arguments to the Message type used by the // core evm. This method is used in calls and traces that do not require a real // live transaction. -func (arg *CallArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (types.Message, error) { +func (arg *CallArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*core.Message, error) { // Reject invalid combinations of pre- and post-1559 fee styles if arg.GasPrice != nil && (arg.MaxFeePerGas != nil || arg.MaxPriorityFeePerGas != nil) { - return types.Message{}, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") + return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") } // Set sender address or use zero address if none specified. addr := arg.from() @@ -189,7 +191,19 @@ func (arg *CallArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (types.Mes if arg.AccessList != nil { accessList = *arg.AccessList } - msg := types.NewMessage(addr, arg.To, 0, value, gas, gasPrice, gasFeeCap, gasTipCap, data, accessList, true) + msg := &core.Message{ + Nonce: 0, + GasLimit: gas, + GasPrice: new(big.Int).Set(gasPrice), + GasFeeCap: new(big.Int).Set(gasFeeCap), + GasTipCap: new(big.Int).Set(gasTipCap), + To: arg.To, + Value: value, + Data: data, + AccessList: accessList, + SkipAccountChecks: true, + From: addr, + } return msg, nil }