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:
parent
742b6d1300
commit
b59d9a23ea
@ -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
|
||||||
|
@ -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())
|
||||||
|
@ -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) {}
|
||||||
|
Loading…
Reference in New Issue
Block a user