evm: add ApplyNativeMessage (#557)

* add ApplyNativeMessage

Closes #533

* fix lint

* Update x/evm/types/tracer.go

Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>

* Update x/evm/types/tracer.go

Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>

* no-op tracer

Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
Co-authored-by: Federico Kunze <federico.kunze94@gmail.com>
This commit is contained in:
yihuang 2021-09-17 23:23:51 +08:00 committed by GitHub
parent 742b6d1300
commit b59d9a23ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 2 deletions

View File

@ -362,7 +362,7 @@ func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
} }
// NOTE: pass in an empty coinbase address and nil tracer as we don't need them for the check below // NOTE: pass in an empty coinbase address and nil tracer as we don't need them for the check below
evm := ctd.evmKeeper.NewEVM(coreMsg, ethCfg, params, common.Address{}, nil) evm := ctd.evmKeeper.NewEVM(coreMsg, ethCfg, params, common.Address{}, evmtypes.NewNoOpTracer())
// check that caller has enough balance to cover asset transfer for **topmost** call // check that caller has enough balance to cover asset transfer for **topmost** call
// NOTE: here the gas consumed is from the context with the infinite gas meter // NOTE: here the gas consumed is from the context with the infinite gas meter

View File

@ -311,6 +311,38 @@ func (k *Keeper) ApplyMessage(evm *vm.EVM, msg core.Message, cfg *params.ChainCo
}, nil }, nil
} }
// ApplyNativeMessage executes an ethereum message on the EVM. It is meant to be called from an internal
// native Cosmos SDK module.
func (k *Keeper) ApplyNativeMessage(msg core.Message) (*types.MsgEthereumTxResponse, error) {
// TODO: clean up and remove duplicate code.
ctx := k.Ctx()
params := k.GetParams(ctx)
// return error if contract creation or call are disabled through governance
if !params.EnableCreate && msg.To() == nil {
return nil, stacktrace.Propagate(types.ErrCreateDisabled, "failed to create new contract")
} else if !params.EnableCall && msg.To() != nil {
return nil, stacktrace.Propagate(types.ErrCallDisabled, "failed to call contract")
}
ethCfg := params.ChainConfig.EthereumConfig(k.eip155ChainID)
// get the coinbase address from the block proposer
coinbase, err := k.GetCoinbaseAddress(ctx)
if err != nil {
return nil, stacktrace.Propagate(err, "failed to obtain coinbase address")
}
evm := k.NewEVM(msg, ethCfg, params, coinbase, nil)
ret, err := k.ApplyMessage(evm, msg, ethCfg, true)
if err != nil {
return nil, err
}
k.CommitCachedContexts()
return ret, nil
}
// GetEthIntrinsicGas returns the intrinsic gas cost for the transaction // GetEthIntrinsicGas returns the intrinsic gas cost for the transaction
func (k *Keeper) GetEthIntrinsicGas(msg core.Message, cfg *params.ChainConfig, isContractCreation bool) (uint64, error) { func (k *Keeper) GetEthIntrinsicGas(msg core.Message, cfg *params.ChainConfig, isContractCreation bool) (uint64, error) {
height := big.NewInt(k.Ctx().BlockHeight()) height := big.NewInt(k.Ctx().BlockHeight())

View File

@ -4,7 +4,9 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"os" "os"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -36,7 +38,7 @@ func NewTracer(tracer string, msg core.Message, cfg *params.ChainConfig, height
case TracerStruct: case TracerStruct:
return vm.NewStructLogger(logCfg) return vm.NewStructLogger(logCfg)
default: default:
return nil return NewNoOpTracer()
} }
} }
@ -112,3 +114,28 @@ func FormatLogs(logs []vm.StructLog) []StructLogRes {
} }
return formatted return formatted
} }
var _ vm.Tracer = &NoOpTracer{}
// NoOpTracer is an empty implementation of vm.Tracer interface
type NoOpTracer struct{}
// NewNoOpTracer creates a no-op vm.Tracer
func NewNoOpTracer() *NoOpTracer {
return &NoOpTracer{}
}
// CaptureStart implements vm.Tracer interface
func (dt NoOpTracer) CaptureStart(env *vm.EVM, from, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
}
// CaptureState implements vm.Tracer interface
func (dt NoOpTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
}
// CaptureFault implements vm.Tracer interface
func (dt NoOpTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
}
// CaptureEnd implements vm.Tracer interface
func (dt NoOpTracer) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {}