forked from cerc-io/laconicd-deprecated
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
|
### 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#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`.
|
* (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.
|
* (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
|
### 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#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:
|
* (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.
|
* The `TxReceipt`, `TxReceiptsByBlockHeight` endpoints have been removed from the Query service.
|
||||||
@ -65,6 +68,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||||||
|
|
||||||
### Improvements
|
### 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)
|
* (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.
|
* (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.
|
* (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)
|
WithContext(ctx sdk.Context)
|
||||||
ResetRefundTransient(ctx sdk.Context)
|
ResetRefundTransient(ctx sdk.Context)
|
||||||
GetCoinbaseAddress() (common.Address, error)
|
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
|
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
|
// 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{})
|
evm := ctd.evmKeeper.NewEVM(coreMsg, ethCfg, params, common.Address{}, "")
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -96,6 +96,7 @@ import (
|
|||||||
_ "github.com/tharsis/ethermint/client/docs/statik"
|
_ "github.com/tharsis/ethermint/client/docs/statik"
|
||||||
|
|
||||||
"github.com/tharsis/ethermint/app/ante"
|
"github.com/tharsis/ethermint/app/ante"
|
||||||
|
srvflags "github.com/tharsis/ethermint/server/flags"
|
||||||
ethermint "github.com/tharsis/ethermint/types"
|
ethermint "github.com/tharsis/ethermint/types"
|
||||||
"github.com/tharsis/ethermint/x/evm"
|
"github.com/tharsis/ethermint/x/evm"
|
||||||
evmrest "github.com/tharsis/ethermint/x/evm/client/rest"
|
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())
|
app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.BaseApp.MsgServiceRouter())
|
||||||
|
|
||||||
|
tracer := cast.ToString(appOpts.Get(srvflags.EVMTracer))
|
||||||
|
|
||||||
// Create Ethermint keepers
|
// Create Ethermint keepers
|
||||||
app.EvmKeeper = evmkeeper.NewKeeper(
|
app.EvmKeeper = evmkeeper.NewKeeper(
|
||||||
appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], app.GetSubspace(evmtypes.ModuleName),
|
appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], app.GetSubspace(evmtypes.ModuleName),
|
||||||
app.AccountKeeper, app.BankKeeper, app.StakingKeeper,
|
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
|
// Create IBC Keeper
|
||||||
@ -388,7 +391,7 @@ func NewEthermintApp(
|
|||||||
|
|
||||||
// NOTE: we may consider parsing `appOpts` inside module constructors. For the moment
|
// NOTE: we may consider parsing `appOpts` inside module constructors. For the moment
|
||||||
// we prefer to be more strict in what arguments the modules expect.
|
// 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
|
// NOTE: Any module instantiated in the module manager that is later modified
|
||||||
// must be passed by reference here.
|
// must be passed by reference here.
|
||||||
|
@ -38,6 +38,7 @@ import (
|
|||||||
"github.com/tharsis/ethermint/encoding"
|
"github.com/tharsis/ethermint/encoding"
|
||||||
"github.com/tharsis/ethermint/server"
|
"github.com/tharsis/ethermint/server"
|
||||||
servercfg "github.com/tharsis/ethermint/server/config"
|
servercfg "github.com/tharsis/ethermint/server/config"
|
||||||
|
srvflags "github.com/tharsis/ethermint/server/flags"
|
||||||
ethermint "github.com/tharsis/ethermint/types"
|
ethermint "github.com/tharsis/ethermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -115,7 +116,7 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
|
|||||||
txCommand(),
|
txCommand(),
|
||||||
ethermintclient.KeyCommands(app.DefaultNodeHome),
|
ethermintclient.KeyCommands(app.DefaultNodeHome),
|
||||||
)
|
)
|
||||||
rootCmd = server.AddTxFlags(rootCmd)
|
rootCmd = srvflags.AddTxFlags(rootCmd)
|
||||||
|
|
||||||
// add rosetta
|
// add rosetta
|
||||||
rootCmd.AddCommand(sdkserver.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Marshaler))
|
rootCmd.AddCommand(sdkserver.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Marshaler))
|
||||||
|
@ -14,7 +14,7 @@ build:
|
|||||||
init:
|
init:
|
||||||
home: "$HOME/.ethermintd"
|
home: "$HOME/.ethermintd"
|
||||||
app:
|
app:
|
||||||
evm-rpc:
|
json-rpc:
|
||||||
address: "0.0.0.0:8545" # change the JSON-RPC address and port
|
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
|
ws-address: "0.0.0.0:8546" # change the JSON-RPC websocket address and port
|
||||||
genesis:
|
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
|
PubSubAPI](https://geth.ethereum.org/docs/rpc/pubsub), Ethermint needs to cast the Tendermint
|
||||||
responses retreived into the Ethereum types.
|
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"`):
|
the node (default `"0.0.0.0:8546"`):
|
||||||
|
|
||||||
```bash
|
```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)
|
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).
|
To enable RPC server use the following flag (set to true by default).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ethermintd start --evm-rpc.enable
|
ethermintd start --json-rpc.enable
|
||||||
```
|
```
|
||||||
|
|
||||||
## Defining Namespaces
|
## 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
|
```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
|
### 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:
|
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
|
```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).
|
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 -->
|
<!-- 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:
|
To start your node, just type:
|
||||||
|
|
||||||
```bash
|
```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
|
## Key Management
|
||||||
|
2
init.sh
2
init.sh
@ -86,4 +86,4 @@ if [[ $1 == "pending" ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Start the node (remove the --pruning=nothing flag if historical queries are not needed)
|
# 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
|
"$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
|
# 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
|
# Give ethermintd node enough time to launch
|
||||||
sleep 5
|
sleep 5
|
||||||
|
@ -106,7 +106,7 @@ start_func() {
|
|||||||
echo "starting ethermint node $i in background ..."
|
echo "starting ethermint node $i in background ..."
|
||||||
"$PWD"/build/ethermintd start --pruning=nothing --rpc.unsafe \
|
"$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" \
|
--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" \
|
--keyring-backend test --home "$DATA_DIR$i" \
|
||||||
>"$DATA_DIR"/node"$i".log 2>&1 & disown
|
>"$DATA_DIR"/node"$i".log 2>&1 & disown
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ start_func() {
|
|||||||
echo "starting ethermint node $i in background ..."
|
echo "starting ethermint node $i in background ..."
|
||||||
"$PWD"/build/ethermintd start --pruning=nothing --rpc.unsafe \
|
"$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" \
|
--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" \
|
--keyring-backend test --home "$DATA_DIR$i" \
|
||||||
>"$DATA_DIR"/node"$i".log 2>&1 & disown
|
>"$DATA_DIR"/node"$i".log 2>&1 & disown
|
||||||
|
|
||||||
|
@ -1,19 +1,33 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/cosmos/cosmos-sdk/server/config"
|
"fmt"
|
||||||
|
|
||||||
"github.com/spf13/viper"
|
"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 (
|
const (
|
||||||
// DefaultGRPCAddress is the default address the gRPC server binds to.
|
// DefaultGRPCAddress is the default address the gRPC server binds to.
|
||||||
DefaultGRPCAddress = "0.0.0.0:9900"
|
DefaultGRPCAddress = "0.0.0.0:9900"
|
||||||
|
|
||||||
// DefaultEVMAddress is the default address the EVM JSON-RPC server binds to.
|
// DefaultJSONRPCAddress is the default address the JSON-RPC server binds to.
|
||||||
DefaultEVMAddress = "0.0.0.0:8545"
|
DefaultJSONRPCAddress = "0.0.0.0:8545"
|
||||||
|
|
||||||
// DefaultEVMWSAddress is the default address the EVM WebSocket server binds to.
|
// DefaultJSONRPCWsAddress is the default address the JSON-RPC WebSocket server binds to.
|
||||||
DefaultEVMWSAddress = "0.0.0.0:8546"
|
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
|
// GetDefaultAPINamespaces returns the default list of JSON-RPC namespaces that should be enabled
|
||||||
@ -45,8 +59,9 @@ func AppConfig(denom string) (string, interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
customAppConfig := Config{
|
customAppConfig := Config{
|
||||||
Config: *srvCfg,
|
Config: *srvCfg,
|
||||||
EVMRPC: *DefaultEVMConfig(),
|
EVM: *DefaultEVMConfig(),
|
||||||
|
JSONRPC: *DefaultJSONRPCConfig(),
|
||||||
}
|
}
|
||||||
|
|
||||||
customAppTemplate := config.DefaultConfigTemplate + DefaultConfigTemplate
|
customAppTemplate := config.DefaultConfigTemplate + DefaultConfigTemplate
|
||||||
@ -57,15 +72,39 @@ func AppConfig(denom string) (string, interface{}) {
|
|||||||
// DefaultConfig returns server's default configuration.
|
// DefaultConfig returns server's default configuration.
|
||||||
func DefaultConfig() *Config {
|
func DefaultConfig() *Config {
|
||||||
return &Config{
|
return &Config{
|
||||||
Config: *config.DefaultConfig(),
|
Config: *config.DefaultConfig(),
|
||||||
EVMRPC: *DefaultEVMConfig(),
|
EVM: *DefaultEVMConfig(),
|
||||||
|
JSONRPC: *DefaultJSONRPCConfig(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EVMRPCConfig defines configuration for the EVM RPC server.
|
// EVMConfig defines the application configuration values for the EVM.
|
||||||
type EVMRPCConfig struct {
|
type EVMConfig struct {
|
||||||
// RPCAddress defines the HTTP server to listen on
|
// Tracer defines vm.Tracer type that the EVM will use if the node is run in
|
||||||
RPCAddress string `mapstructure:"address"`
|
// 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 defines the WebSocket server to listen on
|
||||||
WsAddress string `mapstructure:"ws-address"`
|
WsAddress string `mapstructure:"ws-address"`
|
||||||
// API defines a list of JSON-RPC namespaces that should be enabled
|
// 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"`
|
EnableUnsafeCORS bool `mapstructure:"enable-unsafe-cors"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultEVMConfig returns an EVM config with the JSON-RPC API enabled by default
|
// DefaultJSONRPCConfig returns an EVM config with the JSON-RPC API enabled by default
|
||||||
func DefaultEVMConfig() *EVMRPCConfig {
|
func DefaultJSONRPCConfig() *JSONRPCConfig {
|
||||||
return &EVMRPCConfig{
|
return &JSONRPCConfig{
|
||||||
Enable: true,
|
Enable: true,
|
||||||
API: GetDefaultAPINamespaces(),
|
API: GetDefaultAPINamespaces(),
|
||||||
RPCAddress: DefaultEVMAddress,
|
Address: DefaultJSONRPCAddress,
|
||||||
WsAddress: DefaultEVMWSAddress,
|
WsAddress: DefaultJSONRPCWsAddress,
|
||||||
EnableUnsafeCORS: false,
|
EnableUnsafeCORS: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,7 +131,8 @@ func DefaultEVMConfig() *EVMRPCConfig {
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
config.Config
|
config.Config
|
||||||
|
|
||||||
EVMRPC EVMRPCConfig `mapstructure:"evm-rpc"`
|
EVM EVMConfig `mapstructure:"evm"`
|
||||||
|
JSONRPC JSONRPCConfig `mapstructure:"json-rpc"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetConfig returns a fully parsed Config object.
|
// GetConfig returns a fully parsed Config object.
|
||||||
@ -101,12 +141,26 @@ func GetConfig(v *viper.Viper) Config {
|
|||||||
|
|
||||||
return Config{
|
return Config{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
EVMRPC: EVMRPCConfig{
|
EVM: EVMConfig{
|
||||||
Enable: v.GetBool("evm-rpc.enable"),
|
Tracer: v.GetString("evm.tracer"),
|
||||||
API: v.GetStringSlice("evm-rpc.api"),
|
},
|
||||||
RPCAddress: v.GetString("evm-rpc.address"),
|
JSONRPC: JSONRPCConfig{
|
||||||
WsAddress: v.GetString("evm-rpc.ws-address"),
|
Enable: v.GetBool("json-rpc.enable"),
|
||||||
EnableUnsafeCORS: v.GetBool("evm-rpc.enable-unsafe-cors"),
|
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) {
|
func TestDefaultConfig(t *testing.T) {
|
||||||
cfg := DefaultEVMConfig()
|
cfg := DefaultConfig()
|
||||||
require.True(t, cfg.Enable)
|
require.True(t, cfg.JSONRPC.Enable)
|
||||||
require.Equal(t, cfg.RPCAddress, DefaultEVMAddress)
|
require.Equal(t, cfg.JSONRPC.Address, DefaultJSONRPCAddress)
|
||||||
require.Equal(t, cfg.WsAddress, DefaultEVMWSAddress)
|
require.Equal(t, cfg.JSONRPC.WsAddress, DefaultJSONRPCWsAddress)
|
||||||
}
|
}
|
||||||
|
@ -3,24 +3,35 @@ package config
|
|||||||
// DefaultConfigTemplate defines the configuration template for the EVM RPC configuration
|
// DefaultConfigTemplate defines the configuration template for the EVM RPC configuration
|
||||||
const DefaultConfigTemplate = `
|
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 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 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.
|
# 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
|
# API defines a list of JSON-RPC namespaces that should be enabled
|
||||||
# Example: "eth,txpool,personal,net,debug,web3"
|
# 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)
|
# 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 (
|
import (
|
||||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||||
@ -7,6 +7,37 @@ import (
|
|||||||
"github.com/spf13/viper"
|
"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
|
// AddTxFlags adds common flags for commands to post tx
|
||||||
func AddTxFlags(cmd *cobra.Command) *cobra.Command {
|
func AddTxFlags(cmd *cobra.Command) *cobra.Command {
|
||||||
cmd.PersistentFlags().String(flags.FlagChainID, "testnet", "Specify Chain ID for sending Tx")
|
cmd.PersistentFlags().String(flags.FlagChainID, "testnet", "Specify Chain ID for sending Tx")
|
@ -17,19 +17,19 @@ import (
|
|||||||
"github.com/tharsis/ethermint/server/config"
|
"github.com/tharsis/ethermint/server/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StartEVMRPC start evm rpc server
|
// StartJSONRPC starts the JSON-RPC server
|
||||||
func StartEVMRPC(ctx *server.Context, clientCtx client.Context, tmRPCAddr string, tmEndpoint string, config config.Config) (*http.Server, chan struct{}, error) {
|
func StartJSONRPC(ctx *server.Context, clientCtx client.Context, tmRPCAddr string, tmEndpoint string, config config.Config) (*http.Server, chan struct{}, error) {
|
||||||
tmWsClient := ConnectTmWS(tmRPCAddr, tmEndpoint)
|
tmWsClient := ConnectTmWS(tmRPCAddr, tmEndpoint)
|
||||||
|
|
||||||
rpcServer := ethrpc.NewServer()
|
rpcServer := ethrpc.NewServer()
|
||||||
|
|
||||||
rpcAPIArr := config.EVMRPC.API
|
rpcAPIArr := config.JSONRPC.API
|
||||||
apis := rpc.GetRPCAPIs(ctx, clientCtx, tmWsClient, rpcAPIArr)
|
apis := rpc.GetRPCAPIs(ctx, clientCtx, tmWsClient, rpcAPIArr)
|
||||||
|
|
||||||
for _, api := range apis {
|
for _, api := range apis {
|
||||||
if err := rpcServer.RegisterName(api.Namespace, api.Service); err != nil {
|
if err := rpcServer.RegisterName(api.Namespace, api.Service); err != nil {
|
||||||
ctx.Logger.Error(
|
ctx.Logger.Error(
|
||||||
"failed to register service in EVM RPC namespace",
|
"failed to register service in JSON RPC namespace",
|
||||||
"namespace", api.Namespace,
|
"namespace", api.Namespace,
|
||||||
"service", api.Service,
|
"service", api.Service,
|
||||||
)
|
)
|
||||||
@ -41,43 +41,43 @@ func StartEVMRPC(ctx *server.Context, clientCtx client.Context, tmRPCAddr string
|
|||||||
r.HandleFunc("/", rpcServer.ServeHTTP).Methods("POST")
|
r.HandleFunc("/", rpcServer.ServeHTTP).Methods("POST")
|
||||||
|
|
||||||
handlerWithCors := cors.Default()
|
handlerWithCors := cors.Default()
|
||||||
if config.EVMRPC.EnableUnsafeCORS {
|
if config.JSONRPC.EnableUnsafeCORS {
|
||||||
handlerWithCors = cors.AllowAll()
|
handlerWithCors = cors.AllowAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
httpSrv := &http.Server{
|
httpSrv := &http.Server{
|
||||||
Addr: config.EVMRPC.RPCAddress,
|
Addr: config.JSONRPC.Address,
|
||||||
Handler: handlerWithCors.Handler(r),
|
Handler: handlerWithCors.Handler(r),
|
||||||
}
|
}
|
||||||
httpSrvDone := make(chan struct{}, 1)
|
httpSrvDone := make(chan struct{}, 1)
|
||||||
|
|
||||||
errCh := make(chan error)
|
errCh := make(chan error)
|
||||||
go func() {
|
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 := httpSrv.ListenAndServe(); err != nil {
|
||||||
if err == http.ErrServerClosed {
|
if err == http.ErrServerClosed {
|
||||||
close(httpSrvDone)
|
close(httpSrvDone)
|
||||||
return
|
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
|
errCh <- err
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case err := <-errCh:
|
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
|
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)
|
ctx.Logger.Info("Starting JSON WebSocket server", "address", config.JSONRPC.WsAddress)
|
||||||
_, port, _ := net.SplitHostPort(config.EVMRPC.RPCAddress)
|
_, port, _ := net.SplitHostPort(config.JSONRPC.Address)
|
||||||
|
|
||||||
// allocate separate WS connection to Tendermint
|
// allocate separate WS connection to Tendermint
|
||||||
tmWsClient = ConnectTmWS(tmRPCAddr, tmEndpoint)
|
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()
|
wsSrv.Start()
|
||||||
return httpSrv, httpSrvDone, nil
|
return httpSrv, httpSrvDone, nil
|
||||||
}
|
}
|
130
server/start.go
130
server/start.go
@ -8,6 +8,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime/pprof"
|
"runtime/pprof"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
@ -42,48 +43,7 @@ import (
|
|||||||
|
|
||||||
ethdebug "github.com/tharsis/ethermint/ethereum/rpc/namespaces/debug"
|
ethdebug "github.com/tharsis/ethermint/ethereum/rpc/namespaces/debug"
|
||||||
"github.com/tharsis/ethermint/server/config"
|
"github.com/tharsis/ethermint/server/config"
|
||||||
)
|
srvflags "github.com/tharsis/ethermint/server/flags"
|
||||||
|
|
||||||
// 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"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// StartCmd runs the service passed in, either stand-alone or in-process with
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
withTM, _ := cmd.Flags().GetBool(flagWithTendermint)
|
withTM, _ := cmd.Flags().GetBool(srvflags.WithTendermint)
|
||||||
if !withTM {
|
if !withTM {
|
||||||
serverCtx.Logger.Info("starting ABCI without Tendermint")
|
serverCtx.Logger.Info("starting ABCI without Tendermint")
|
||||||
return startStandAlone(serverCtx, appCreator)
|
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().String(flags.FlagHome, defaultNodeHome, "The application home directory")
|
||||||
cmd.Flags().Bool(flagWithTendermint, true, "Run abci app embedded in-process with tendermint")
|
cmd.Flags().Bool(srvflags.WithTendermint, true, "Run abci app embedded in-process with tendermint")
|
||||||
cmd.Flags().String(flagAddress, "tcp://0.0.0.0:26658", "Listen address")
|
cmd.Flags().String(srvflags.Address, "tcp://0.0.0.0:26658", "Listen address")
|
||||||
cmd.Flags().String(flagTransport, "socket", "Transport protocol: socket, grpc")
|
cmd.Flags().String(srvflags.Transport, "socket", "Transport protocol: socket, grpc")
|
||||||
cmd.Flags().String(flagTraceStore, "", "Enable KVStore tracing to an output file")
|
cmd.Flags().String(srvflags.TraceStore, "", "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().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(FlagUnsafeSkipUpgrades, []int{}, "Skip a set of upgrade heights to continue the old binary")
|
cmd.Flags().IntSlice(server.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(server.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().Uint64(server.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().Bool(server.FlagInterBlockCache, true, "Enable inter-block caching")
|
||||||
cmd.Flags().String(flagCPUProfile, "", "Enable CPU profiling and write to the provided file")
|
cmd.Flags().String(srvflags.CPUProfile, "", "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().Bool(server.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().String(server.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(server.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(server.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().Uint64(server.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().Uint(server.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().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().Bool(srvflags.GRPCEnable, true, "Define if the gRPC server should be enabled")
|
||||||
cmd.Flags().String(flagGRPCAddress, serverconfig.DefaultGRPCAddress, "the gRPC server address to listen on")
|
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().Bool(srvflags.JSONRPCEnable, true, "Define if the gRPC server should be enabled")
|
||||||
cmd.Flags().String(flagGRPCWebAddress, serverconfig.DefaultGRPCWebAddress, "The gRPC-Web server address to listen on")
|
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().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().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().Uint64(FlagStateSyncSnapshotInterval, 0, "State sync snapshot interval")
|
cmd.Flags().Uint64(server.FlagStateSyncSnapshotInterval, 0, "State sync snapshot interval")
|
||||||
cmd.Flags().Uint32(FlagStateSyncSnapshotKeepRecent, 2, "State sync snapshot to keep")
|
cmd.Flags().Uint32(server.FlagStateSyncSnapshotKeepRecent, 2, "State sync snapshot to keep")
|
||||||
|
|
||||||
// add support for all Tendermint-specific command line options
|
// add support for all Tendermint-specific command line options
|
||||||
tcmd.AddNodeFlags(cmd)
|
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 {
|
func startStandAlone(ctx *server.Context, appCreator types.AppCreator) error {
|
||||||
addr := ctx.Viper.GetString(flagAddress)
|
addr := ctx.Viper.GetString(srvflags.Address)
|
||||||
transport := ctx.Viper.GetString(flagTransport)
|
transport := ctx.Viper.GetString(srvflags.Transport)
|
||||||
home := ctx.Viper.GetString(flags.FlagHome)
|
home := ctx.Viper.GetString(flags.FlagHome)
|
||||||
|
|
||||||
db, err := openDB(home)
|
db, err := openDB(home)
|
||||||
@ -203,7 +164,7 @@ func startStandAlone(ctx *server.Context, appCreator types.AppCreator) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
traceWriterFile := ctx.Viper.GetString(flagTraceStore)
|
traceWriterFile := ctx.Viper.GetString(srvflags.TraceStore)
|
||||||
traceWriter, err := openTraceWriter(traceWriterFile)
|
traceWriter, err := openTraceWriter(traceWriterFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -240,7 +201,7 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
|
|||||||
logger := ctx.Logger
|
logger := ctx.Logger
|
||||||
var cpuProfileCleanup func()
|
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))
|
f, err := os.Create(ethdebug.ExpandHome(cpuProfile))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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)
|
db, err := openDB(home)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("failed to open DB", "error", err.Error())
|
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)
|
config := config.GetConfig(ctx.Viper)
|
||||||
|
|
||||||
if err := config.ValidateBasic(); err != nil {
|
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") {
|
||||||
"This defaults to 0 in the current version, but will error in the next version " +
|
ctx.Logger.Error(
|
||||||
"(SDK v0.44). Please explicitly put the desired minimum-gas-prices in your app.toml.")
|
"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.",
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
app := appCreator(ctx.Logger, db, traceWriter, ctx.Viper)
|
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
|
httpSrv *http.Server
|
||||||
httpSrvDone chan struct{}
|
httpSrvDone chan struct{}
|
||||||
)
|
)
|
||||||
if config.EVMRPC.Enable {
|
if config.JSONRPC.Enable {
|
||||||
genDoc, err := genDocProvider()
|
genDoc, err := genDocProvider()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -415,7 +383,7 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
|
|||||||
|
|
||||||
tmEndpoint := "/websocket"
|
tmEndpoint := "/websocket"
|
||||||
tmRPCAddr := cfg.RPC.ListenAddress
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -43,4 +43,4 @@ ethermintd collect-gentxs
|
|||||||
ethermintd validate-genesis
|
ethermintd validate-genesis
|
||||||
|
|
||||||
# Start the node (remove the --pruning=nothing flag if historical queries are not needed)
|
# 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 := ""
|
jsonRPCAddr := ""
|
||||||
tmCfg.RPC.ListenAddress = ""
|
tmCfg.RPC.ListenAddress = ""
|
||||||
appCfg.GRPC.Enable = false
|
appCfg.GRPC.Enable = false
|
||||||
appCfg.EVMRPC.Enable = false
|
appCfg.JSONRPC.Enable = false
|
||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
apiListenAddr, _, err := server.FreeTCPAddr()
|
apiListenAddr, _, err := server.FreeTCPAddr()
|
||||||
@ -244,8 +244,8 @@ func New(t *testing.T, cfg Config) *Network {
|
|||||||
jsonRPCListenAddr, _, err := server.FreeTCPAddr()
|
jsonRPCListenAddr, _, err := server.FreeTCPAddr()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
t.Log(jsonRPCListenAddr)
|
t.Log(jsonRPCListenAddr)
|
||||||
appCfg.EVMRPC.RPCAddress = jsonRPCListenAddr
|
appCfg.JSONRPC.Address = jsonRPCListenAddr
|
||||||
appCfg.EVMRPC.Enable = true
|
appCfg.JSONRPC.Enable = true
|
||||||
|
|
||||||
jsonRPCAPIURL, err := url.Parse(jsonRPCListenAddr)
|
jsonRPCAPIURL, err := url.Parse(jsonRPCListenAddr)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -114,14 +114,14 @@ func startInProcess(cfg Config, val *Validator) error {
|
|||||||
val.grpc = grpcSrv
|
val.grpc = grpcSrv
|
||||||
}
|
}
|
||||||
|
|
||||||
if val.AppConfig.EVMRPC.Enable {
|
if val.AppConfig.JSONRPC.Enable {
|
||||||
tmEndpoint := "/websocket"
|
tmEndpoint := "/websocket"
|
||||||
tmRPCAddr := val.Ctx.Config.RPC.ListenAddress
|
tmRPCAddr := val.Ctx.Config.RPC.ListenAddress
|
||||||
tmWsClient := ethsrv.ConnectTmWS(tmRPCAddr, tmEndpoint)
|
tmWsClient := ethsrv.ConnectTmWS(tmRPCAddr, tmEndpoint)
|
||||||
|
|
||||||
val.jsonRPC = jsonrpc.NewServer()
|
val.jsonRPC = jsonrpc.NewServer()
|
||||||
|
|
||||||
rpcAPIArr := val.AppConfig.EVMRPC.API
|
rpcAPIArr := val.AppConfig.JSONRPC.API
|
||||||
apis := rpc.GetRPCAPIs(val.Ctx, val.ClientCtx, tmWsClient, rpcAPIArr)
|
apis := rpc.GetRPCAPIs(val.Ctx, val.ClientCtx, tmWsClient, rpcAPIArr)
|
||||||
|
|
||||||
for _, api := range apis {
|
for _, api := range apis {
|
||||||
@ -153,8 +153,8 @@ func startInProcess(cfg Config, val *Validator) error {
|
|||||||
})
|
})
|
||||||
|
|
||||||
httpSrv := &http.Server{
|
httpSrv := &http.Server{
|
||||||
Addr: strings.TrimPrefix(val.AppConfig.EVMRPC.RPCAddress, "tcp://"), // FIXME: timeouts
|
Addr: strings.TrimPrefix(val.AppConfig.JSONRPC.Address, "tcp://"), // FIXME: timeouts
|
||||||
// Addr: val.AppConfig.EVMRPC.RPCAddress, // FIXME: address has too many colons
|
// Addr: val.AppConfig.JSONRPC.RPCAddress, // FIXME: address has too many colons
|
||||||
Handler: handlerWithCors.Handler(r),
|
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())
|
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.
|
// pass true means execute in query mode, which don't do actual gas refund.
|
||||||
res, err := k.ApplyMessage(evm, msg, ethCfg, true)
|
res, err := k.ApplyMessage(evm, msg, ethCfg, true)
|
||||||
k.ctxStack.RevertAll()
|
k.ctxStack.RevertAll()
|
||||||
@ -448,7 +449,7 @@ func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (*type
|
|||||||
k.WithContext(ctx)
|
k.WithContext(ctx)
|
||||||
|
|
||||||
msg := args.ToMessage(req.GasCap)
|
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.
|
// pass true means execute in query mode, which don't do actual gas refund.
|
||||||
rsp, err := k.ApplyMessage(evm, msg, ethCfg, true)
|
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
|
// chain ID number obtained from the context's chain id
|
||||||
eip155ChainID *big.Int
|
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.
|
// trace EVM state transition execution. This value is obtained from the `--trace` flag.
|
||||||
// For more info check https://geth.ethereum.org/docs/dapp/tracing
|
// For more info check https://geth.ethereum.org/docs/dapp/tracing
|
||||||
debug bool
|
debug bool
|
||||||
@ -58,7 +61,7 @@ func NewKeeper(
|
|||||||
cdc codec.BinaryCodec,
|
cdc codec.BinaryCodec,
|
||||||
storeKey, transientKey sdk.StoreKey, paramSpace paramtypes.Subspace,
|
storeKey, transientKey sdk.StoreKey, paramSpace paramtypes.Subspace,
|
||||||
ak types.AccountKeeper, bankKeeper types.BankKeeper, sk types.StakingKeeper,
|
ak types.AccountKeeper, bankKeeper types.BankKeeper, sk types.StakingKeeper,
|
||||||
debug bool,
|
tracer string, debug bool,
|
||||||
) *Keeper {
|
) *Keeper {
|
||||||
|
|
||||||
// ensure evm module account is set
|
// ensure evm module account is set
|
||||||
@ -80,6 +83,7 @@ func NewKeeper(
|
|||||||
stakingKeeper: sk,
|
stakingKeeper: sk,
|
||||||
storeKey: storeKey,
|
storeKey: storeKey,
|
||||||
transientKey: transientKey,
|
transientKey: transientKey,
|
||||||
|
tracer: tracer,
|
||||||
debug: debug,
|
debug: debug,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package keeper
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/palantir/stacktrace"
|
"github.com/palantir/stacktrace"
|
||||||
@ -28,7 +27,13 @@ import (
|
|||||||
// (ChainConfig and module Params). It additionally sets the validator operator address as the
|
// (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
|
// 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).
|
// 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{
|
blockCtx := vm.BlockContext{
|
||||||
CanTransfer: core.CanTransfer,
|
CanTransfer: core.CanTransfer,
|
||||||
Transfer: core.Transfer,
|
Transfer: core.Transfer,
|
||||||
@ -41,18 +46,20 @@ func (k *Keeper) NewEVM(msg core.Message, config *params.ChainConfig, params typ
|
|||||||
}
|
}
|
||||||
|
|
||||||
txCtx := core.NewEVMTxContext(msg)
|
txCtx := core.NewEVMTxContext(msg)
|
||||||
vmConfig := k.VMConfig(params)
|
vmConfig := k.VMConfig(msg, params, tracer)
|
||||||
|
|
||||||
return vm.NewEVM(blockCtx, txCtx, k, config, vmConfig)
|
return vm.NewEVM(blockCtx, txCtx, k, config, vmConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
// VMConfig creates an EVM configuration from the debug setting and the extra EIPs enabled on the
|
// 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.
|
// 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{
|
return vm.Config{
|
||||||
Debug: k.debug,
|
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
|
NoRecursion: false, // TODO: consider disabling recursion though params
|
||||||
ExtraEips: params.EIPs(),
|
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
|
// 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()
|
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