evm, server: configurable tracer (#434)
* server: update server and enable configurable tracer * config validation * fix import cycle * fix start * update fields * c++ * c++
This commit is contained in:
parent
353455def9
commit
cc3b2ff8e9
@ -39,6 +39,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
### State Machine Breaking
|
||||
|
||||
* (app, evm) [tharsis#434](https://github.com/tharsis/ethermint/pull/434) EVM `Keeper` struct and `NewEVM` function now have a new `trace` field to define
|
||||
the Tracer type used to collect execution traces from the EVM transaction execution.
|
||||
* (evm) [tharsis#175](https://github.com/tharsis/ethermint/issues/175) The msg `TxData` field is now represented as a `*proto.Any`.
|
||||
* (evm) [tharsis#84](https://github.com/tharsis/ethermint/pull/84) Remove `journal`, `CommitStateDB` and `stateObjects`.
|
||||
* (rpc, evm) [tharsis#81](https://github.com/tharsis/ethermint/pull/81) Remove tx `Receipt` from store and replace it with fields obtained from the Tendermint RPC client.
|
||||
@ -53,6 +55,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
### API Breaking
|
||||
|
||||
* (server) [tharsis#434](https://github.com/tharsis/ethermint/pull/434) `evm-rpc` flags and app config have been renamed to `json-rpc`.
|
||||
* (proto, evm) [tharsis#207](https://github.com/tharsis/ethermint/issues/207) Replace `big.Int` in favor of `sdk.Int` for `TxData` fields
|
||||
* (proto, evm) [tharsis#81](https://github.com/tharsis/ethermint/pull/81) gRPC Query and Tx service changes:
|
||||
* The `TxReceipt`, `TxReceiptsByBlockHeight` endpoints have been removed from the Query service.
|
||||
@ -65,6 +68,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
### Improvements
|
||||
|
||||
* (evm) [tharsis#434](https://github.com/tharsis/ethermint/pull/434) Support different `Tracer` types for the EVM.
|
||||
* (deps) [tharsis#427](https://github.com/tharsis/ethermint/pull/427) Bump ibc-go to [`v1.0.0`](https://github.com/cosmos/ibc-go/releases/tag/v1.0.0)
|
||||
* (gRPC) [tharsis#239](https://github.com/tharsis/ethermint/pull/239) Query `ChainConfig` via gRPC.
|
||||
* (rpc) [tharsis#181](https://github.com/tharsis/ethermint/pull/181) Use evm denomination for params on tx fee.
|
||||
|
@ -27,7 +27,7 @@ type EVMKeeper interface {
|
||||
WithContext(ctx sdk.Context)
|
||||
ResetRefundTransient(ctx sdk.Context)
|
||||
GetCoinbaseAddress() (common.Address, error)
|
||||
NewEVM(msg core.Message, config *params.ChainConfig, params evmtypes.Params, coinbase common.Address) *vm.EVM
|
||||
NewEVM(msg core.Message, config *params.ChainConfig, params evmtypes.Params, coinbase common.Address, tracer string) *vm.EVM
|
||||
GetCodeHash(addr common.Address) common.Hash
|
||||
}
|
||||
|
||||
@ -389,8 +389,8 @@ func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
|
||||
)
|
||||
}
|
||||
|
||||
// NOTE: pass in an empty coinbase address as we don't need it for the check below
|
||||
evm := ctd.evmKeeper.NewEVM(coreMsg, ethCfg, params, common.Address{})
|
||||
// NOTE: pass in an empty coinbase address and tracer as we don't need them for the check below
|
||||
evm := ctd.evmKeeper.NewEVM(coreMsg, ethCfg, params, common.Address{}, "")
|
||||
|
||||
// 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
|
||||
|
@ -96,6 +96,7 @@ import (
|
||||
_ "github.com/tharsis/ethermint/client/docs/statik"
|
||||
|
||||
"github.com/tharsis/ethermint/app/ante"
|
||||
srvflags "github.com/tharsis/ethermint/server/flags"
|
||||
ethermint "github.com/tharsis/ethermint/types"
|
||||
"github.com/tharsis/ethermint/x/evm"
|
||||
evmrest "github.com/tharsis/ethermint/x/evm/client/rest"
|
||||
@ -333,11 +334,13 @@ func NewEthermintApp(
|
||||
|
||||
app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.BaseApp.MsgServiceRouter())
|
||||
|
||||
tracer := cast.ToString(appOpts.Get(srvflags.EVMTracer))
|
||||
|
||||
// Create Ethermint keepers
|
||||
app.EvmKeeper = evmkeeper.NewKeeper(
|
||||
appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], app.GetSubspace(evmtypes.ModuleName),
|
||||
app.AccountKeeper, app.BankKeeper, app.StakingKeeper,
|
||||
bApp.Trace(), // debug EVM based on Baseapp options
|
||||
tracer, bApp.Trace(), // debug EVM based on Baseapp options
|
||||
)
|
||||
|
||||
// Create IBC Keeper
|
||||
@ -388,7 +391,7 @@ func NewEthermintApp(
|
||||
|
||||
// NOTE: we may consider parsing `appOpts` inside module constructors. For the moment
|
||||
// we prefer to be more strict in what arguments the modules expect.
|
||||
var skipGenesisInvariants = cast.ToBool(appOpts.Get(crisis.FlagSkipGenesisInvariants))
|
||||
skipGenesisInvariants := cast.ToBool(appOpts.Get(crisis.FlagSkipGenesisInvariants))
|
||||
|
||||
// NOTE: Any module instantiated in the module manager that is later modified
|
||||
// must be passed by reference here.
|
||||
|
@ -38,6 +38,7 @@ import (
|
||||
"github.com/tharsis/ethermint/encoding"
|
||||
"github.com/tharsis/ethermint/server"
|
||||
servercfg "github.com/tharsis/ethermint/server/config"
|
||||
srvflags "github.com/tharsis/ethermint/server/flags"
|
||||
ethermint "github.com/tharsis/ethermint/types"
|
||||
)
|
||||
|
||||
@ -115,7 +116,7 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
|
||||
txCommand(),
|
||||
ethermintclient.KeyCommands(app.DefaultNodeHome),
|
||||
)
|
||||
rootCmd = server.AddTxFlags(rootCmd)
|
||||
rootCmd = srvflags.AddTxFlags(rootCmd)
|
||||
|
||||
// add rosetta
|
||||
rootCmd.AddCommand(sdkserver.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Marshaler))
|
||||
|
@ -14,7 +14,7 @@ build:
|
||||
init:
|
||||
home: "$HOME/.ethermintd"
|
||||
app:
|
||||
evm-rpc:
|
||||
json-rpc:
|
||||
address: "0.0.0.0:8545" # change the JSON-RPC address and port
|
||||
ws-address: "0.0.0.0:8546" # change the JSON-RPC websocket address and port
|
||||
genesis:
|
||||
|
@ -111,11 +111,11 @@ compatibility for websockets of the [Ethereum's
|
||||
PubSubAPI](https://geth.ethereum.org/docs/rpc/pubsub), Ethermint needs to cast the Tendermint
|
||||
responses retreived into the Ethereum types.
|
||||
|
||||
You can start a connection with the Ethereum websocket using the `--evm-rpc.ws-address` flag when starting
|
||||
You can start a connection with the Ethereum websocket using the `--json-rpc.ws-address` flag when starting
|
||||
the node (default `"0.0.0.0:8546"`):
|
||||
|
||||
```bash
|
||||
ethermintd start --evm-rpc.address"0.0.0.0:8545" --evm-rpc.ws-address="0.0.0.0:8546" --evm.rpc.api="eth,web3,net,txpool,debug" --evm-rpc.enable
|
||||
ethermintd start --json-rpc.address"0.0.0.0:8545" --json-rpc.ws-address="0.0.0.0:8546" --evm.rpc.api="eth,web3,net,txpool,debug" --json-rpc.enable
|
||||
```
|
||||
|
||||
Then, start a websocket subscription with [`ws`](https://github.com/hashrocket/ws)
|
||||
|
@ -11,15 +11,15 @@ Learn how to run and setup the JSON-RPC server on Ethermint. {synopsis}
|
||||
To enable RPC server use the following flag (set to true by default).
|
||||
|
||||
```bash
|
||||
ethermintd start --evm-rpc.enable
|
||||
ethermintd start --json-rpc.enable
|
||||
```
|
||||
|
||||
## Defining Namespaces
|
||||
|
||||
`Eth`,`Net` and `Web3` [namespaces](./namespaces) are enabled by default. In order to enable other namespaces use flag `--evm-rpc.api`.
|
||||
`Eth`,`Net` and `Web3` [namespaces](./namespaces) are enabled by default. In order to enable other namespaces use flag `--json-rpc.api`.
|
||||
|
||||
```bash
|
||||
ethermintd start --evm-rpc.api eth,txpool,personal,net,debug,web3,miner
|
||||
ethermintd start --json-rpc.api eth,txpool,personal,net,debug,web3,miner
|
||||
```
|
||||
|
||||
### CORS
|
||||
@ -27,5 +27,5 @@ ethermintd start --evm-rpc.api eth,txpool,personal,net,debug,web3,miner
|
||||
If accessing the RPC from a browser, CORS will need to be enabled with the appropriate domain set. Otherwise, JavaScript calls are limit by the same-origin policy and requests will fail:
|
||||
|
||||
```bash
|
||||
ethermintd start --evm-rpc.enable-unsafe-cors
|
||||
ethermintd start --json-rpc.enable-unsafe-cors
|
||||
```
|
||||
|
@ -24,6 +24,6 @@ APIs](./../api/JSON-RPC/running_server) to connect with existing web3 tooling.
|
||||
See the list of supported JSON-RPC API [endpoints](./../api/JSON-RPC/endpoints) and [namespaces](./../api/JSON-RPC/namespaces).
|
||||
:::
|
||||
|
||||
To connect to the JSON-PRC server, start the node with the `--evm-rpc.enable=true` flag and define the namespaces that you would like to run using the `--evm.rpc.api` flag (e.g. `"txpool,eth,web3,net,personal"`. Then, you can point any Ethereum development tooling to `http://localhost:8545` or whatever port you choose with the listen address flag (`--evm-rpc.address`).
|
||||
To connect to the JSON-PRC server, start the node with the `--json-rpc.enable=true` flag and define the namespaces that you would like to run using the `--evm.rpc.api` flag (e.g. `"txpool,eth,web3,net,personal"`. Then, you can point any Ethereum development tooling to `http://localhost:8545` or whatever port you choose with the listen address flag (`--json-rpc.address`).
|
||||
|
||||
<!-- TODO: add Rosetta -->
|
@ -38,7 +38,7 @@ The instructions for setting up a brand new full node from scratch are the the s
|
||||
To start your node, just type:
|
||||
|
||||
```bash
|
||||
ethermintd start --evm-rpc.enable=true --evm-rpc.api="eth,web3,net,txpool,debug"
|
||||
ethermintd start --json-rpc.enable=true --json-rpc.api="eth,web3,net,txpool,debug"
|
||||
```
|
||||
|
||||
## Key Management
|
||||
|
2
init.sh
2
init.sh
@ -86,4 +86,4 @@ if [[ $1 == "pending" ]]; then
|
||||
fi
|
||||
|
||||
# Start the node (remove the --pruning=nothing flag if historical queries are not needed)
|
||||
ethermintd start --pruning=nothing $TRACE --log_level $LOGLEVEL --minimum-gas-prices=0.0001aphoton --evm-rpc.api eth,txpool,personal,net,debug,web3,miner
|
||||
ethermintd start --pruning=nothing $TRACE --log_level $LOGLEVEL --minimum-gas-prices=0.0001aphoton --json-rpc.api eth,txpool,personal,net,debug,web3,miner
|
||||
|
@ -35,7 +35,7 @@ cat $HOME/.ethermint/config/genesis.json | jq '.app_state["mint"]["params"]["min
|
||||
"$PWD"/build/ethermintd validate-genesis
|
||||
|
||||
# Start the node (remove the --pruning=nothing flag if historical queries are not needed) in background and log to file
|
||||
"$PWD"/build/ethermintd start --pruning=nothing --rpc.unsafe --evm-rpc.address="0.0.0.0:8545" --keyring-backend test > ethermintd.log 2>&1 &
|
||||
"$PWD"/build/ethermintd start --pruning=nothing --rpc.unsafe --json-rpc.address="0.0.0.0:8545" --keyring-backend test > ethermintd.log 2>&1 &
|
||||
|
||||
# Give ethermintd node enough time to launch
|
||||
sleep 5
|
||||
|
@ -106,7 +106,7 @@ start_func() {
|
||||
echo "starting ethermint node $i in background ..."
|
||||
"$PWD"/build/ethermintd start --pruning=nothing --rpc.unsafe \
|
||||
--p2p.laddr tcp://$IP_ADDR:$NODE_P2P_PORT"$i" --address tcp://$IP_ADDR:$NODE_PORT"$i" --rpc.laddr tcp://$IP_ADDR:$NODE_RPC_PORT"$i" \
|
||||
--evm-rpc.address=$IP_ADDR:$RPC_PORT"$i" \
|
||||
--json-rpc.address=$IP_ADDR:$RPC_PORT"$i" \
|
||||
--keyring-backend test --home "$DATA_DIR$i" \
|
||||
>"$DATA_DIR"/node"$i".log 2>&1 & disown
|
||||
|
||||
|
@ -92,7 +92,7 @@ start_func() {
|
||||
echo "starting ethermint node $i in background ..."
|
||||
"$PWD"/build/ethermintd start --pruning=nothing --rpc.unsafe \
|
||||
--p2p.laddr tcp://$IP_ADDR:$NODE_P2P_PORT"$i" --address tcp://$IP_ADDR:$NODE_PORT"$i" --rpc.laddr tcp://$IP_ADDR:$NODE_RPC_PORT"$i" \
|
||||
--evm-rpc.address=$IP_ADDR:$RPC_PORT"$i" \
|
||||
--json-rpc.address=$IP_ADDR:$RPC_PORT"$i" \
|
||||
--keyring-backend test --home "$DATA_DIR$i" \
|
||||
>"$DATA_DIR"/node"$i".log 2>&1 & disown
|
||||
|
||||
|
@ -1,19 +1,33 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/server/config"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/tendermint/tendermint/libs/strings"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/server/config"
|
||||
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultGRPCAddress is the default address the gRPC server binds to.
|
||||
DefaultGRPCAddress = "0.0.0.0:9900"
|
||||
|
||||
// DefaultEVMAddress is the default address the EVM JSON-RPC server binds to.
|
||||
DefaultEVMAddress = "0.0.0.0:8545"
|
||||
// DefaultJSONRPCAddress is the default address the JSON-RPC server binds to.
|
||||
DefaultJSONRPCAddress = "0.0.0.0:8545"
|
||||
|
||||
// DefaultEVMWSAddress is the default address the EVM WebSocket server binds to.
|
||||
DefaultEVMWSAddress = "0.0.0.0:8546"
|
||||
// DefaultJSONRPCWsAddress is the default address the JSON-RPC WebSocket server binds to.
|
||||
DefaultJSONRPCWsAddress = "0.0.0.0:8546"
|
||||
|
||||
// DefaultEVMTracer is the default vm.Tracer type
|
||||
DefaultEVMTracer = "json"
|
||||
)
|
||||
|
||||
var (
|
||||
evmTracers = []string{DefaultEVMTracer, "markdown", "struct", "access_list"}
|
||||
)
|
||||
|
||||
// GetDefaultAPINamespaces returns the default list of JSON-RPC namespaces that should be enabled
|
||||
@ -46,7 +60,8 @@ func AppConfig(denom string) (string, interface{}) {
|
||||
|
||||
customAppConfig := Config{
|
||||
Config: *srvCfg,
|
||||
EVMRPC: *DefaultEVMConfig(),
|
||||
EVM: *DefaultEVMConfig(),
|
||||
JSONRPC: *DefaultJSONRPCConfig(),
|
||||
}
|
||||
|
||||
customAppTemplate := config.DefaultConfigTemplate + DefaultConfigTemplate
|
||||
@ -58,14 +73,38 @@ func AppConfig(denom string) (string, interface{}) {
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
Config: *config.DefaultConfig(),
|
||||
EVMRPC: *DefaultEVMConfig(),
|
||||
EVM: *DefaultEVMConfig(),
|
||||
JSONRPC: *DefaultJSONRPCConfig(),
|
||||
}
|
||||
}
|
||||
|
||||
// EVMRPCConfig defines configuration for the EVM RPC server.
|
||||
type EVMRPCConfig struct {
|
||||
// RPCAddress defines the HTTP server to listen on
|
||||
RPCAddress string `mapstructure:"address"`
|
||||
// EVMConfig defines the application configuration values for the EVM.
|
||||
type EVMConfig struct {
|
||||
// Tracer defines vm.Tracer type that the EVM will use if the node is run in
|
||||
// trace mode. Default: 'json'.
|
||||
Tracer string `mapstructure:"tracer"`
|
||||
}
|
||||
|
||||
// DefaultEVMConfig returns the default EVM configuration
|
||||
func DefaultEVMConfig() *EVMConfig {
|
||||
return &EVMConfig{
|
||||
Tracer: DefaultEVMTracer,
|
||||
}
|
||||
}
|
||||
|
||||
// Validate returns an error if the tracer type is invalid.
|
||||
func (c EVMConfig) Validate() error {
|
||||
if !strings.StringInSlice(c.Tracer, evmTracers) {
|
||||
return fmt.Errorf("invalid tracer type %s, available types: %v", c.Tracer, evmTracers)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// JSONRPCConfig defines configuration for the EVM RPC server.
|
||||
type JSONRPCConfig struct {
|
||||
// Address defines the HTTP server to listen on
|
||||
Address string `mapstructure:"address"`
|
||||
// WsAddress defines the WebSocket server to listen on
|
||||
WsAddress string `mapstructure:"ws-address"`
|
||||
// API defines a list of JSON-RPC namespaces that should be enabled
|
||||
@ -76,13 +115,13 @@ type EVMRPCConfig struct {
|
||||
EnableUnsafeCORS bool `mapstructure:"enable-unsafe-cors"`
|
||||
}
|
||||
|
||||
// DefaultEVMConfig returns an EVM config with the JSON-RPC API enabled by default
|
||||
func DefaultEVMConfig() *EVMRPCConfig {
|
||||
return &EVMRPCConfig{
|
||||
// DefaultJSONRPCConfig returns an EVM config with the JSON-RPC API enabled by default
|
||||
func DefaultJSONRPCConfig() *JSONRPCConfig {
|
||||
return &JSONRPCConfig{
|
||||
Enable: true,
|
||||
API: GetDefaultAPINamespaces(),
|
||||
RPCAddress: DefaultEVMAddress,
|
||||
WsAddress: DefaultEVMWSAddress,
|
||||
Address: DefaultJSONRPCAddress,
|
||||
WsAddress: DefaultJSONRPCWsAddress,
|
||||
EnableUnsafeCORS: false,
|
||||
}
|
||||
}
|
||||
@ -92,7 +131,8 @@ func DefaultEVMConfig() *EVMRPCConfig {
|
||||
type Config struct {
|
||||
config.Config
|
||||
|
||||
EVMRPC EVMRPCConfig `mapstructure:"evm-rpc"`
|
||||
EVM EVMConfig `mapstructure:"evm"`
|
||||
JSONRPC JSONRPCConfig `mapstructure:"json-rpc"`
|
||||
}
|
||||
|
||||
// GetConfig returns a fully parsed Config object.
|
||||
@ -101,12 +141,26 @@ func GetConfig(v *viper.Viper) Config {
|
||||
|
||||
return Config{
|
||||
Config: cfg,
|
||||
EVMRPC: EVMRPCConfig{
|
||||
Enable: v.GetBool("evm-rpc.enable"),
|
||||
API: v.GetStringSlice("evm-rpc.api"),
|
||||
RPCAddress: v.GetString("evm-rpc.address"),
|
||||
WsAddress: v.GetString("evm-rpc.ws-address"),
|
||||
EnableUnsafeCORS: v.GetBool("evm-rpc.enable-unsafe-cors"),
|
||||
EVM: EVMConfig{
|
||||
Tracer: v.GetString("evm.tracer"),
|
||||
},
|
||||
JSONRPC: JSONRPCConfig{
|
||||
Enable: v.GetBool("json-rpc.enable"),
|
||||
API: v.GetStringSlice("json-rpc.api"),
|
||||
Address: v.GetString("json-rpc.address"),
|
||||
WsAddress: v.GetString("json-rpc.ws-address"),
|
||||
EnableUnsafeCORS: v.GetBool("json-rpc.enable-unsafe-cors"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateBasic returns an error any of the application configuration fields are invalid
|
||||
func (c Config) ValidateBasic() error {
|
||||
if err := c.EVM.Validate(); err != nil {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrAppConfig, "invalid evm config value: %s", err.Error())
|
||||
}
|
||||
|
||||
// TODO: validate JSON-RPC APIs
|
||||
|
||||
return c.Config.ValidateBasic()
|
||||
}
|
||||
|
@ -7,8 +7,8 @@ import (
|
||||
)
|
||||
|
||||
func TestDefaultConfig(t *testing.T) {
|
||||
cfg := DefaultEVMConfig()
|
||||
require.True(t, cfg.Enable)
|
||||
require.Equal(t, cfg.RPCAddress, DefaultEVMAddress)
|
||||
require.Equal(t, cfg.WsAddress, DefaultEVMWSAddress)
|
||||
cfg := DefaultConfig()
|
||||
require.True(t, cfg.JSONRPC.Enable)
|
||||
require.Equal(t, cfg.JSONRPC.Address, DefaultJSONRPCAddress)
|
||||
require.Equal(t, cfg.JSONRPC.WsAddress, DefaultJSONRPCWsAddress)
|
||||
}
|
||||
|
@ -3,24 +3,35 @@ package config
|
||||
// DefaultConfigTemplate defines the configuration template for the EVM RPC configuration
|
||||
const DefaultConfigTemplate = `
|
||||
###############################################################################
|
||||
### EVM RPC Configuration ###
|
||||
### EVM Configuration ###
|
||||
###############################################################################
|
||||
|
||||
[evm-rpc]
|
||||
[evm]
|
||||
|
||||
# Tracer defines the 'vm.Tracer' type that the EVM will use when the node is run in
|
||||
# debug mode. To enable tracing use the '--trace' flag when starting your node.
|
||||
# Valid types are: json|struct|access_list|markdown
|
||||
tracer = "{{ .EVM.Tracer }}"
|
||||
|
||||
###############################################################################
|
||||
### JSON RPC Configuration ###
|
||||
###############################################################################
|
||||
|
||||
[json-rpc]
|
||||
|
||||
# Enable defines if the gRPC server should be enabled.
|
||||
enable = {{ .EVMRPC.Enable }}
|
||||
enable = {{ .JSONRPC.Enable }}
|
||||
|
||||
# Address defines the EVM RPC HTTP server address to bind to.
|
||||
address = "{{ .EVMRPC.RPCAddress }}"
|
||||
address = "{{ .JSONRPC.Address }}"
|
||||
|
||||
# Address defines the EVM WebSocket server address to bind to.
|
||||
ws-address = "{{ .EVMRPC.WsAddress }}"
|
||||
ws-address = "{{ .JSONRPC.WsAddress }}"
|
||||
|
||||
# API defines a list of JSON-RPC namespaces that should be enabled
|
||||
# Example: "eth,txpool,personal,net,debug,web3"
|
||||
api = "{{range $index, $elmt := .EVMRPC.API}}{{if $index}},{{$elmt}}{{else}}{{$elmt}}{{end}}{{end}}"
|
||||
api = "{{range $index, $elmt := .JSONRPC.API}}{{if $index}},{{$elmt}}{{else}}{{$elmt}}{{end}}{{end}}"
|
||||
|
||||
# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk)
|
||||
enable-unsafe-cors = "{{ .EVMRPC.EnableUnsafeCORS }}"
|
||||
enable-unsafe-cors = "{{ .JSONRPC.EnableUnsafeCORS }}"
|
||||
`
|
||||
|
@ -1,4 +1,4 @@
|
||||
package server
|
||||
package flags
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
@ -7,6 +7,37 @@ import (
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// Tendermint full-node start flags
|
||||
const (
|
||||
WithTendermint = "with-tendermint"
|
||||
Address = "address"
|
||||
Transport = "transport"
|
||||
TraceStore = "trace-store"
|
||||
CPUProfile = "cpu-profile"
|
||||
)
|
||||
|
||||
// GRPC-related flags.
|
||||
const (
|
||||
GRPCEnable = "grpc.enable"
|
||||
GRPCAddress = "grpc.address"
|
||||
GRPCWebEnable = "grpc-web.enable"
|
||||
GRPCWebAddress = "grpc-web.address"
|
||||
)
|
||||
|
||||
// JSON-RPC flags
|
||||
const (
|
||||
JSONRPCEnable = "json-rpc.enable"
|
||||
JSONRPCAPI = "json-rpc.api"
|
||||
JSONRPCAddress = "json-rpc.address"
|
||||
JSONWsAddress = "json-rpc.ws-address"
|
||||
JSONEnableUnsafeCORS = "json-rpc.enable-unsafe-cors"
|
||||
)
|
||||
|
||||
// EVM flags
|
||||
const (
|
||||
EVMTracer = "evm.tracer"
|
||||
)
|
||||
|
||||
// AddTxFlags adds common flags for commands to post tx
|
||||
func AddTxFlags(cmd *cobra.Command) *cobra.Command {
|
||||
cmd.PersistentFlags().String(flags.FlagChainID, "testnet", "Specify Chain ID for sending Tx")
|
@ -17,19 +17,19 @@ import (
|
||||
"github.com/tharsis/ethermint/server/config"
|
||||
)
|
||||
|
||||
// StartEVMRPC start evm rpc server
|
||||
func StartEVMRPC(ctx *server.Context, clientCtx client.Context, tmRPCAddr string, tmEndpoint string, config config.Config) (*http.Server, chan struct{}, error) {
|
||||
// StartJSONRPC starts the JSON-RPC server
|
||||
func StartJSONRPC(ctx *server.Context, clientCtx client.Context, tmRPCAddr string, tmEndpoint string, config config.Config) (*http.Server, chan struct{}, error) {
|
||||
tmWsClient := ConnectTmWS(tmRPCAddr, tmEndpoint)
|
||||
|
||||
rpcServer := ethrpc.NewServer()
|
||||
|
||||
rpcAPIArr := config.EVMRPC.API
|
||||
rpcAPIArr := config.JSONRPC.API
|
||||
apis := rpc.GetRPCAPIs(ctx, clientCtx, tmWsClient, rpcAPIArr)
|
||||
|
||||
for _, api := range apis {
|
||||
if err := rpcServer.RegisterName(api.Namespace, api.Service); err != nil {
|
||||
ctx.Logger.Error(
|
||||
"failed to register service in EVM RPC namespace",
|
||||
"failed to register service in JSON RPC namespace",
|
||||
"namespace", api.Namespace,
|
||||
"service", api.Service,
|
||||
)
|
||||
@ -41,43 +41,43 @@ func StartEVMRPC(ctx *server.Context, clientCtx client.Context, tmRPCAddr string
|
||||
r.HandleFunc("/", rpcServer.ServeHTTP).Methods("POST")
|
||||
|
||||
handlerWithCors := cors.Default()
|
||||
if config.EVMRPC.EnableUnsafeCORS {
|
||||
if config.JSONRPC.EnableUnsafeCORS {
|
||||
handlerWithCors = cors.AllowAll()
|
||||
}
|
||||
|
||||
httpSrv := &http.Server{
|
||||
Addr: config.EVMRPC.RPCAddress,
|
||||
Addr: config.JSONRPC.Address,
|
||||
Handler: handlerWithCors.Handler(r),
|
||||
}
|
||||
httpSrvDone := make(chan struct{}, 1)
|
||||
|
||||
errCh := make(chan error)
|
||||
go func() {
|
||||
ctx.Logger.Info("Starting EVM RPC server", "address", config.EVMRPC.RPCAddress)
|
||||
ctx.Logger.Info("Starting JSON-RPC server", "address", config.JSONRPC.Address)
|
||||
if err := httpSrv.ListenAndServe(); err != nil {
|
||||
if err == http.ErrServerClosed {
|
||||
close(httpSrvDone)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Logger.Error("failed to start EVM RPC server", "error", err.Error())
|
||||
ctx.Logger.Error("failed to start JSON-RPC server", "error", err.Error())
|
||||
errCh <- err
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case err := <-errCh:
|
||||
ctx.Logger.Error("failed to boot EVM RPC server", "error", err.Error())
|
||||
ctx.Logger.Error("failed to boot JSON-RPC server", "error", err.Error())
|
||||
return nil, nil, err
|
||||
case <-time.After(types.ServerStartTime): // assume EVM RPC server started successfully
|
||||
case <-time.After(types.ServerStartTime): // assume JSON RPC server started successfully
|
||||
}
|
||||
|
||||
ctx.Logger.Info("Starting EVM WebSocket server", "address", config.EVMRPC.WsAddress)
|
||||
_, port, _ := net.SplitHostPort(config.EVMRPC.RPCAddress)
|
||||
ctx.Logger.Info("Starting JSON WebSocket server", "address", config.JSONRPC.WsAddress)
|
||||
_, port, _ := net.SplitHostPort(config.JSONRPC.Address)
|
||||
|
||||
// allocate separate WS connection to Tendermint
|
||||
tmWsClient = ConnectTmWS(tmRPCAddr, tmEndpoint)
|
||||
wsSrv := rpc.NewWebsocketsServer(ctx.Logger, tmWsClient, "localhost:"+port, config.EVMRPC.WsAddress)
|
||||
wsSrv := rpc.NewWebsocketsServer(ctx.Logger, tmWsClient, "localhost:"+port, config.JSONRPC.WsAddress)
|
||||
wsSrv.Start()
|
||||
return httpSrv, httpSrvDone, nil
|
||||
}
|
128
server/start.go
128
server/start.go
@ -8,6 +8,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime/pprof"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
@ -42,48 +43,7 @@ import (
|
||||
|
||||
ethdebug "github.com/tharsis/ethermint/ethereum/rpc/namespaces/debug"
|
||||
"github.com/tharsis/ethermint/server/config"
|
||||
)
|
||||
|
||||
// Tendermint full-node start flags
|
||||
const (
|
||||
flagWithTendermint = "with-tendermint"
|
||||
flagAddress = "address"
|
||||
flagTransport = "transport"
|
||||
flagTraceStore = "trace-store"
|
||||
flagCPUProfile = "cpu-profile"
|
||||
FlagMinGasPrices = "minimum-gas-prices"
|
||||
FlagHaltHeight = "halt-height"
|
||||
FlagHaltTime = "halt-time"
|
||||
FlagInterBlockCache = "inter-block-cache"
|
||||
FlagUnsafeSkipUpgrades = "unsafe-skip-upgrades"
|
||||
FlagTrace = "trace"
|
||||
FlagInvCheckPeriod = "inv-check-period"
|
||||
|
||||
FlagPruning = "pruning"
|
||||
FlagPruningKeepRecent = "pruning-keep-recent"
|
||||
FlagPruningKeepEvery = "pruning-keep-every"
|
||||
FlagPruningInterval = "pruning-interval"
|
||||
FlagIndexEvents = "index-events"
|
||||
FlagMinRetainBlocks = "min-retain-blocks"
|
||||
)
|
||||
|
||||
// GRPC-related flags.
|
||||
const (
|
||||
flagGRPCEnable = "grpc.enable"
|
||||
flagGRPCAddress = "grpc.address"
|
||||
flagEVMRPCEnable = "evm-rpc.enable"
|
||||
flagEVMRPCAPI = "evm-rpc.api"
|
||||
flagEVMRPCAddress = "evm-rpc.address"
|
||||
flagEVMWSAddress = "evm-rpc.ws-address"
|
||||
flagEVMEnableUnsafeCORS = "evm-rpc.enable-unsafe-cors"
|
||||
flagGRPCWebEnable = "grpc-web.enable"
|
||||
flagGRPCWebAddress = "grpc-web.address"
|
||||
)
|
||||
|
||||
// State sync-related flags.
|
||||
const (
|
||||
FlagStateSyncSnapshotInterval = "state-sync.snapshot-interval"
|
||||
FlagStateSyncSnapshotKeepRecent = "state-sync.snapshot-keep-recent"
|
||||
srvflags "github.com/tharsis/ethermint/server/flags"
|
||||
)
|
||||
|
||||
// StartCmd runs the service passed in, either stand-alone or in-process with
|
||||
@ -134,7 +94,7 @@ which accepts a path for the resulting pprof file.
|
||||
return err
|
||||
}
|
||||
|
||||
withTM, _ := cmd.Flags().GetBool(flagWithTendermint)
|
||||
withTM, _ := cmd.Flags().GetBool(srvflags.WithTendermint)
|
||||
if !withTM {
|
||||
serverCtx.Logger.Info("starting ABCI without Tendermint")
|
||||
return startStandAlone(serverCtx, appCreator)
|
||||
@ -155,38 +115,39 @@ which accepts a path for the resulting pprof file.
|
||||
}
|
||||
|
||||
cmd.Flags().String(flags.FlagHome, defaultNodeHome, "The application home directory")
|
||||
cmd.Flags().Bool(flagWithTendermint, true, "Run abci app embedded in-process with tendermint")
|
||||
cmd.Flags().String(flagAddress, "tcp://0.0.0.0:26658", "Listen address")
|
||||
cmd.Flags().String(flagTransport, "socket", "Transport protocol: socket, grpc")
|
||||
cmd.Flags().String(flagTraceStore, "", "Enable KVStore tracing to an output file")
|
||||
cmd.Flags().String(FlagMinGasPrices, "", "Minimum gas prices to accept for transactions; Any fee in a tx must meet this minimum (e.g. 0.01photino;0.0001stake)")
|
||||
cmd.Flags().IntSlice(FlagUnsafeSkipUpgrades, []int{}, "Skip a set of upgrade heights to continue the old binary")
|
||||
cmd.Flags().Uint64(FlagHaltHeight, 0, "Block height at which to gracefully halt the chain and shutdown the node")
|
||||
cmd.Flags().Uint64(FlagHaltTime, 0, "Minimum block time (in Unix seconds) at which to gracefully halt the chain and shutdown the node")
|
||||
cmd.Flags().Bool(FlagInterBlockCache, true, "Enable inter-block caching")
|
||||
cmd.Flags().String(flagCPUProfile, "", "Enable CPU profiling and write to the provided file")
|
||||
cmd.Flags().Bool(FlagTrace, false, "Provide full stack traces for errors in ABCI Log")
|
||||
cmd.Flags().String(FlagPruning, storetypes.PruningOptionDefault, "Pruning strategy (default|nothing|everything|custom)")
|
||||
cmd.Flags().Uint64(FlagPruningKeepRecent, 0, "Number of recent heights to keep on disk (ignored if pruning is not 'custom')")
|
||||
cmd.Flags().Uint64(FlagPruningKeepEvery, 0, "Offset heights to keep on disk after 'keep-every' (ignored if pruning is not 'custom')")
|
||||
cmd.Flags().Uint64(FlagPruningInterval, 0, "Height interval at which pruned heights are removed from disk (ignored if pruning is not 'custom')")
|
||||
cmd.Flags().Uint(FlagInvCheckPeriod, 0, "Assert registered invariants every N blocks")
|
||||
cmd.Flags().Uint64(FlagMinRetainBlocks, 0, "Minimum block height offset during ABCI commit to prune Tendermint blocks")
|
||||
cmd.Flags().Bool(srvflags.WithTendermint, true, "Run abci app embedded in-process with tendermint")
|
||||
cmd.Flags().String(srvflags.Address, "tcp://0.0.0.0:26658", "Listen address")
|
||||
cmd.Flags().String(srvflags.Transport, "socket", "Transport protocol: socket, grpc")
|
||||
cmd.Flags().String(srvflags.TraceStore, "", "Enable KVStore tracing to an output file")
|
||||
cmd.Flags().String(server.FlagMinGasPrices, "", "Minimum gas prices to accept for transactions; Any fee in a tx must meet this minimum (e.g. 0.01photino;0.0001stake)")
|
||||
cmd.Flags().IntSlice(server.FlagUnsafeSkipUpgrades, []int{}, "Skip a set of upgrade heights to continue the old binary")
|
||||
cmd.Flags().Uint64(server.FlagHaltHeight, 0, "Block height at which to gracefully halt the chain and shutdown the node")
|
||||
cmd.Flags().Uint64(server.FlagHaltTime, 0, "Minimum block time (in Unix seconds) at which to gracefully halt the chain and shutdown the node")
|
||||
cmd.Flags().Bool(server.FlagInterBlockCache, true, "Enable inter-block caching")
|
||||
cmd.Flags().String(srvflags.CPUProfile, "", "Enable CPU profiling and write to the provided file")
|
||||
cmd.Flags().Bool(server.FlagTrace, false, "Provide full stack traces for errors in ABCI Log")
|
||||
cmd.Flags().String(server.FlagPruning, storetypes.PruningOptionDefault, "Pruning strategy (default|nothing|everything|custom)")
|
||||
cmd.Flags().Uint64(server.FlagPruningKeepRecent, 0, "Number of recent heights to keep on disk (ignored if pruning is not 'custom')")
|
||||
cmd.Flags().Uint64(server.FlagPruningKeepEvery, 0, "Offset heights to keep on disk after 'keep-every' (ignored if pruning is not 'custom')")
|
||||
cmd.Flags().Uint64(server.FlagPruningInterval, 0, "Height interval at which pruned heights are removed from disk (ignored if pruning is not 'custom')")
|
||||
cmd.Flags().Uint(server.FlagInvCheckPeriod, 0, "Assert registered invariants every N blocks")
|
||||
cmd.Flags().Uint64(server.FlagMinRetainBlocks, 0, "Minimum block height offset during ABCI commit to prune Tendermint blocks")
|
||||
|
||||
cmd.Flags().Bool(flagGRPCEnable, true, "Define if the gRPC server should be enabled")
|
||||
cmd.Flags().String(flagGRPCAddress, serverconfig.DefaultGRPCAddress, "the gRPC server address to listen on")
|
||||
cmd.Flags().Bool(srvflags.GRPCEnable, true, "Define if the gRPC server should be enabled")
|
||||
cmd.Flags().String(srvflags.GRPCAddress, serverconfig.DefaultGRPCAddress, "the gRPC server address to listen on")
|
||||
cmd.Flags().Bool(srvflags.GRPCWebEnable, true, "Define if the gRPC-Web server should be enabled. (Note: gRPC must also be enabled.)")
|
||||
cmd.Flags().String(srvflags.GRPCWebAddress, serverconfig.DefaultGRPCWebAddress, "The gRPC-Web server address to listen on")
|
||||
|
||||
cmd.Flags().Bool(flagGRPCWebEnable, true, "Define if the gRPC-Web server should be enabled. (Note: gRPC must also be enabled.)")
|
||||
cmd.Flags().String(flagGRPCWebAddress, serverconfig.DefaultGRPCWebAddress, "The gRPC-Web server address to listen on")
|
||||
cmd.Flags().Bool(srvflags.JSONRPCEnable, true, "Define if the gRPC server should be enabled")
|
||||
cmd.Flags().StringSlice(srvflags.JSONRPCAPI, config.GetDefaultAPINamespaces(), "Defines a list of JSON-RPC namespaces that should be enabled")
|
||||
cmd.Flags().String(srvflags.JSONRPCAddress, config.DefaultJSONRPCAddress, "the JSON-RPC server address to listen on")
|
||||
cmd.Flags().String(srvflags.JSONWsAddress, config.DefaultJSONRPCWsAddress, "the JSON-RPC WS server address to listen on")
|
||||
cmd.Flags().Bool(srvflags.JSONEnableUnsafeCORS, false, "Define if the JSON-RPC server should enabled CORS (unsafe - use it at your own risk)")
|
||||
|
||||
cmd.Flags().Bool(flagEVMRPCEnable, true, "Define if the gRPC server should be enabled")
|
||||
cmd.Flags().StringSlice(flagEVMRPCAPI, config.GetDefaultAPINamespaces(), "Defines a list of JSON-RPC namespaces that should be enabled")
|
||||
cmd.Flags().String(flagEVMRPCAddress, config.DefaultEVMAddress, "the EVM RPC server address to listen on")
|
||||
cmd.Flags().String(flagEVMWSAddress, config.DefaultEVMWSAddress, "the EVM WS server address to listen on")
|
||||
cmd.Flags().Bool(flagEVMEnableUnsafeCORS, false, "Define if the EVM RPC server should enabled CORS (unsafe - use it at your own risk)")
|
||||
cmd.Flags().String(srvflags.EVMTracer, config.DefaultEVMTracer, "the EVM tracer type to collect execution traces from the EVM transaction execution (json|struct|access_list|markdown)")
|
||||
|
||||
cmd.Flags().Uint64(FlagStateSyncSnapshotInterval, 0, "State sync snapshot interval")
|
||||
cmd.Flags().Uint32(FlagStateSyncSnapshotKeepRecent, 2, "State sync snapshot to keep")
|
||||
cmd.Flags().Uint64(server.FlagStateSyncSnapshotInterval, 0, "State sync snapshot interval")
|
||||
cmd.Flags().Uint32(server.FlagStateSyncSnapshotKeepRecent, 2, "State sync snapshot to keep")
|
||||
|
||||
// add support for all Tendermint-specific command line options
|
||||
tcmd.AddNodeFlags(cmd)
|
||||
@ -194,8 +155,8 @@ which accepts a path for the resulting pprof file.
|
||||
}
|
||||
|
||||
func startStandAlone(ctx *server.Context, appCreator types.AppCreator) error {
|
||||
addr := ctx.Viper.GetString(flagAddress)
|
||||
transport := ctx.Viper.GetString(flagTransport)
|
||||
addr := ctx.Viper.GetString(srvflags.Address)
|
||||
transport := ctx.Viper.GetString(srvflags.Transport)
|
||||
home := ctx.Viper.GetString(flags.FlagHome)
|
||||
|
||||
db, err := openDB(home)
|
||||
@ -203,7 +164,7 @@ func startStandAlone(ctx *server.Context, appCreator types.AppCreator) error {
|
||||
return err
|
||||
}
|
||||
|
||||
traceWriterFile := ctx.Viper.GetString(flagTraceStore)
|
||||
traceWriterFile := ctx.Viper.GetString(srvflags.TraceStore)
|
||||
traceWriter, err := openTraceWriter(traceWriterFile)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -240,7 +201,7 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
|
||||
logger := ctx.Logger
|
||||
var cpuProfileCleanup func()
|
||||
|
||||
if cpuProfile := ctx.Viper.GetString(flagCPUProfile); cpuProfile != "" {
|
||||
if cpuProfile := ctx.Viper.GetString(srvflags.CPUProfile); cpuProfile != "" {
|
||||
f, err := os.Create(ethdebug.ExpandHome(cpuProfile))
|
||||
if err != nil {
|
||||
return err
|
||||
@ -258,7 +219,7 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
|
||||
}
|
||||
}
|
||||
|
||||
traceWriterFile := ctx.Viper.GetString(flagTraceStore)
|
||||
traceWriterFile := ctx.Viper.GetString(srvflags.TraceStore)
|
||||
db, err := openDB(home)
|
||||
if err != nil {
|
||||
logger.Error("failed to open DB", "error", err.Error())
|
||||
@ -272,10 +233,17 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
|
||||
}
|
||||
|
||||
config := config.GetConfig(ctx.Viper)
|
||||
|
||||
if err := config.ValidateBasic(); err != nil {
|
||||
ctx.Logger.Error("WARNING: The minimum-gas-prices config in app.toml is set to the empty string. " +
|
||||
if strings.Contains(err.Error(), "set min gas price in app.toml or flag or env variable") {
|
||||
ctx.Logger.Error(
|
||||
"WARNING: The minimum-gas-prices config in app.toml is set to the empty string. " +
|
||||
"This defaults to 0 in the current version, but will error in the next version " +
|
||||
"(SDK v0.44). Please explicitly put the desired minimum-gas-prices in your app.toml.")
|
||||
"(SDK v0.44). Please explicitly put the desired minimum-gas-prices in your app.toml.",
|
||||
)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
app := appCreator(ctx.Logger, db, traceWriter, ctx.Viper)
|
||||
@ -405,7 +373,7 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
|
||||
httpSrv *http.Server
|
||||
httpSrvDone chan struct{}
|
||||
)
|
||||
if config.EVMRPC.Enable {
|
||||
if config.JSONRPC.Enable {
|
||||
genDoc, err := genDocProvider()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -415,7 +383,7 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
|
||||
|
||||
tmEndpoint := "/websocket"
|
||||
tmRPCAddr := cfg.RPC.ListenAddress
|
||||
httpSrv, httpSrvDone, err = StartEVMRPC(ctx, clientCtx, tmRPCAddr, tmEndpoint, config)
|
||||
httpSrv, httpSrvDone, err = StartJSONRPC(ctx, clientCtx, tmRPCAddr, tmEndpoint, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -43,4 +43,4 @@ ethermintd collect-gentxs
|
||||
ethermintd validate-genesis
|
||||
|
||||
# Start the node (remove the --pruning=nothing flag if historical queries are not needed)
|
||||
ethermintd start --pruning=nothing --rpc.unsafe --keyring-backend test --trace --log_level info --evm-rpc.api eth,txpool,personal,net,debug,web3
|
||||
ethermintd start --pruning=nothing --rpc.unsafe --keyring-backend test --trace --log_level info --json-rpc.api eth,txpool,personal,net,debug,web3
|
||||
|
@ -230,7 +230,7 @@ func New(t *testing.T, cfg Config) *Network {
|
||||
jsonRPCAddr := ""
|
||||
tmCfg.RPC.ListenAddress = ""
|
||||
appCfg.GRPC.Enable = false
|
||||
appCfg.EVMRPC.Enable = false
|
||||
appCfg.JSONRPC.Enable = false
|
||||
|
||||
if i == 0 {
|
||||
apiListenAddr, _, err := server.FreeTCPAddr()
|
||||
@ -244,8 +244,8 @@ func New(t *testing.T, cfg Config) *Network {
|
||||
jsonRPCListenAddr, _, err := server.FreeTCPAddr()
|
||||
require.NoError(t, err)
|
||||
t.Log(jsonRPCListenAddr)
|
||||
appCfg.EVMRPC.RPCAddress = jsonRPCListenAddr
|
||||
appCfg.EVMRPC.Enable = true
|
||||
appCfg.JSONRPC.Address = jsonRPCListenAddr
|
||||
appCfg.JSONRPC.Enable = true
|
||||
|
||||
jsonRPCAPIURL, err := url.Parse(jsonRPCListenAddr)
|
||||
require.NoError(t, err)
|
||||
|
@ -114,14 +114,14 @@ func startInProcess(cfg Config, val *Validator) error {
|
||||
val.grpc = grpcSrv
|
||||
}
|
||||
|
||||
if val.AppConfig.EVMRPC.Enable {
|
||||
if val.AppConfig.JSONRPC.Enable {
|
||||
tmEndpoint := "/websocket"
|
||||
tmRPCAddr := val.Ctx.Config.RPC.ListenAddress
|
||||
tmWsClient := ethsrv.ConnectTmWS(tmRPCAddr, tmEndpoint)
|
||||
|
||||
val.jsonRPC = jsonrpc.NewServer()
|
||||
|
||||
rpcAPIArr := val.AppConfig.EVMRPC.API
|
||||
rpcAPIArr := val.AppConfig.JSONRPC.API
|
||||
apis := rpc.GetRPCAPIs(val.Ctx, val.ClientCtx, tmWsClient, rpcAPIArr)
|
||||
|
||||
for _, api := range apis {
|
||||
@ -153,8 +153,8 @@ func startInProcess(cfg Config, val *Validator) error {
|
||||
})
|
||||
|
||||
httpSrv := &http.Server{
|
||||
Addr: strings.TrimPrefix(val.AppConfig.EVMRPC.RPCAddress, "tcp://"), // FIXME: timeouts
|
||||
// Addr: val.AppConfig.EVMRPC.RPCAddress, // FIXME: address has too many colons
|
||||
Addr: strings.TrimPrefix(val.AppConfig.JSONRPC.Address, "tcp://"), // FIXME: timeouts
|
||||
// Addr: val.AppConfig.JSONRPC.RPCAddress, // FIXME: address has too many colons
|
||||
Handler: handlerWithCors.Handler(r),
|
||||
}
|
||||
|
||||
|
@ -378,7 +378,8 @@ func (k Keeper) EthCall(c context.Context, req *types.EthCallRequest) (*types.Ms
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
evm := k.NewEVM(msg, ethCfg, params, coinbase)
|
||||
evm := k.NewEVM(msg, ethCfg, params, coinbase, k.tracer)
|
||||
|
||||
// pass true means execute in query mode, which don't do actual gas refund.
|
||||
res, err := k.ApplyMessage(evm, msg, ethCfg, true)
|
||||
k.ctxStack.RevertAll()
|
||||
@ -448,7 +449,7 @@ func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (*type
|
||||
k.WithContext(ctx)
|
||||
|
||||
msg := args.ToMessage(req.GasCap)
|
||||
evm := k.NewEVM(msg, ethCfg, params, coinbase)
|
||||
evm := k.NewEVM(msg, ethCfg, params, coinbase, k.tracer)
|
||||
// pass true means execute in query mode, which don't do actual gas refund.
|
||||
rsp, err := k.ApplyMessage(evm, msg, ethCfg, true)
|
||||
|
||||
|
@ -48,6 +48,9 @@ type Keeper struct {
|
||||
|
||||
// chain ID number obtained from the context's chain id
|
||||
eip155ChainID *big.Int
|
||||
|
||||
// Tracer used to collect execution traces from the EVM transaction execution
|
||||
tracer string
|
||||
// trace EVM state transition execution. This value is obtained from the `--trace` flag.
|
||||
// For more info check https://geth.ethereum.org/docs/dapp/tracing
|
||||
debug bool
|
||||
@ -58,7 +61,7 @@ func NewKeeper(
|
||||
cdc codec.BinaryCodec,
|
||||
storeKey, transientKey sdk.StoreKey, paramSpace paramtypes.Subspace,
|
||||
ak types.AccountKeeper, bankKeeper types.BankKeeper, sk types.StakingKeeper,
|
||||
debug bool,
|
||||
tracer string, debug bool,
|
||||
) *Keeper {
|
||||
|
||||
// ensure evm module account is set
|
||||
@ -80,6 +83,7 @@ func NewKeeper(
|
||||
stakingKeeper: sk,
|
||||
storeKey: storeKey,
|
||||
transientKey: transientKey,
|
||||
tracer: tracer,
|
||||
debug: debug,
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package keeper
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/palantir/stacktrace"
|
||||
@ -28,7 +27,13 @@ import (
|
||||
// (ChainConfig and module Params). It additionally sets the validator operator address as the
|
||||
// coinbase address to make it available for the COINBASE opcode, even though there is no
|
||||
// beneficiary of the coinbase transaction (since we're not mining).
|
||||
func (k *Keeper) NewEVM(msg core.Message, config *params.ChainConfig, params types.Params, coinbase common.Address) *vm.EVM {
|
||||
func (k *Keeper) NewEVM(
|
||||
msg core.Message,
|
||||
config *params.ChainConfig,
|
||||
params types.Params,
|
||||
coinbase common.Address,
|
||||
tracer string,
|
||||
) *vm.EVM {
|
||||
blockCtx := vm.BlockContext{
|
||||
CanTransfer: core.CanTransfer,
|
||||
Transfer: core.Transfer,
|
||||
@ -41,17 +46,19 @@ func (k *Keeper) NewEVM(msg core.Message, config *params.ChainConfig, params typ
|
||||
}
|
||||
|
||||
txCtx := core.NewEVMTxContext(msg)
|
||||
vmConfig := k.VMConfig(params)
|
||||
vmConfig := k.VMConfig(msg, params, tracer)
|
||||
|
||||
return vm.NewEVM(blockCtx, txCtx, k, config, vmConfig)
|
||||
}
|
||||
|
||||
// VMConfig creates an EVM configuration from the debug setting and the extra EIPs enabled on the
|
||||
// module parameters. The config generated uses the default JumpTable from the EVM.
|
||||
func (k Keeper) VMConfig(params types.Params) vm.Config {
|
||||
func (k Keeper) VMConfig(msg core.Message, params types.Params, tracer string) vm.Config {
|
||||
cfg := params.ChainConfig.EthereumConfig(k.eip155ChainID)
|
||||
|
||||
return vm.Config{
|
||||
Debug: k.debug,
|
||||
Tracer: vm.NewJSONLogger(&vm.LogConfig{Debug: k.debug}, os.Stderr), // TODO: consider using the Struct Logger too
|
||||
Tracer: types.NewTracer(tracer, msg, cfg, k.Ctx().BlockHeight(), k.debug),
|
||||
NoRecursion: false, // TODO: consider disabling recursion though params
|
||||
ExtraEips: params.EIPs(),
|
||||
}
|
||||
@ -154,7 +161,7 @@ func (k *Keeper) ApplyTransaction(tx *ethtypes.Transaction) (*types.MsgEthereumT
|
||||
}
|
||||
|
||||
// create an ethereum EVM instance and run the message
|
||||
evm := k.NewEVM(msg, ethCfg, params, coinbase)
|
||||
evm := k.NewEVM(msg, ethCfg, params, coinbase, k.tracer)
|
||||
|
||||
txHash := tx.Hash()
|
||||
|
||||
|
40
x/evm/types/tracer.go
Normal file
40
x/evm/types/tracer.go
Normal file
@ -0,0 +1,40 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"os"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
const (
|
||||
TracerAccessList = "access_list"
|
||||
TracerJSON = "json"
|
||||
TracerStruct = "struct"
|
||||
TracerMarkdown = "markdown"
|
||||
)
|
||||
|
||||
// NewTracer creates a new Logger tracer to collect execution traces from an
|
||||
// EVM transaction.
|
||||
func NewTracer(tracer string, msg core.Message, cfg *params.ChainConfig, height int64, debug bool) vm.Tracer {
|
||||
// TODO: enable additional log configuration
|
||||
logCfg := &vm.LogConfig{
|
||||
Debug: debug,
|
||||
}
|
||||
|
||||
switch tracer {
|
||||
case TracerAccessList:
|
||||
precompiles := vm.ActivePrecompiles(cfg.Rules(big.NewInt(height)))
|
||||
return vm.NewAccessListTracer(msg.AccessList(), msg.From(), *msg.To(), precompiles)
|
||||
case TracerJSON:
|
||||
return vm.NewJSONLogger(logCfg, os.Stderr)
|
||||
case TracerMarkdown:
|
||||
return vm.NewMarkdownLogger(logCfg, os.Stdout) // TODO: Stderr ?
|
||||
case TracerStruct:
|
||||
return vm.NewStructLogger(logCfg)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user