Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem: backup grpc clients are not supported #475

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,14 @@
"cosmossdk.io/core/appmodule"
runtimeservices "github.com/cosmos/cosmos-sdk/runtime/services"
"github.com/cosmos/cosmos-sdk/server"
grpc1 "github.com/cosmos/gogoproto/grpc"
"github.com/cosmos/gogoproto/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

"github.com/gorilla/mux"
"github.com/spf13/cast"
"github.com/spf13/viper"

"cosmossdk.io/log"
abci "github.com/cometbft/cometbft/abci/types"
Expand Down Expand Up @@ -132,6 +136,7 @@
"github.com/evmos/ethermint/app/ante"
"github.com/evmos/ethermint/encoding"
"github.com/evmos/ethermint/ethereum/eip712"
srv "github.com/evmos/ethermint/server"
srvconfig "github.com/evmos/ethermint/server/config"
srvflags "github.com/evmos/ethermint/server/flags"
ethermint "github.com/evmos/ethermint/types"
Expand Down Expand Up @@ -249,6 +254,50 @@
configurator module.Configurator
}

func BackupQueryClients[T any](
appOpts servertypes.AppOptions,
interfaceRegistry types.InterfaceRegistry,
queryClientFn func(grpc1.ClientConn) T,
) map[[2]int]T {
backupQueryClients := make(map[[2]int]T)
if v, ok := appOpts.(*viper.Viper); ok {
cfg, err := srvconfig.GetConfig(v)
if err == nil {
maxSendMsgSize := cfg.GRPC.MaxSendMsgSize
if maxSendMsgSize == 0 {
maxSendMsgSize = config.DefaultGRPCMaxSendMsgSize

Check warning on line 268 in app/app.go

View check run for this annotation

Codecov / codecov/patch

app/app.go#L264-L268

Added lines #L264 - L268 were not covered by tests
}

maxRecvMsgSize := cfg.GRPC.MaxRecvMsgSize
if maxRecvMsgSize == 0 {
maxRecvMsgSize = config.DefaultGRPCMaxRecvMsgSize

Check warning on line 273 in app/app.go

View check run for this annotation

Codecov / codecov/patch

app/app.go#L271-L273

Added lines #L271 - L273 were not covered by tests
}

for k, address := range cfg.JSONRPC.BackupGRPCBlockAddressBlockRange {
grpcAddr, err := srv.ParseGRPCAddress(address)
if err != nil {
continue

Check warning on line 279 in app/app.go

View check run for this annotation

Codecov / codecov/patch

app/app.go#L276-L279

Added lines #L276 - L279 were not covered by tests
}

conn, err := grpc.Dial(
grpcAddr,
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithDefaultCallOptions(
grpc.ForceCodec(codec.NewProtoCodec(interfaceRegistry).GRPCCodec()),
grpc.MaxCallRecvMsgSize(maxRecvMsgSize),
grpc.MaxCallSendMsgSize(maxSendMsgSize),
),
)
if err != nil {
continue

Check warning on line 292 in app/app.go

View check run for this annotation

Codecov / codecov/patch

app/app.go#L282-L292

Added lines #L282 - L292 were not covered by tests
}
backupQueryClients[k] = queryClientFn(conn)

Check warning on line 294 in app/app.go

View check run for this annotation

Codecov / codecov/patch

app/app.go#L294

Added line #L294 was not covered by tests
}
Comment on lines +276 to +295

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
}
}
return backupQueryClients
}

// NewEthermintApp returns a reference to a new initialized Ethermint application.
func NewEthermintApp(
logger log.Logger,
Expand Down Expand Up @@ -485,6 +534,7 @@
authtypes.NewModuleAddress(govtypes.ModuleName),
keys[feemarkettypes.StoreKey],
feeMarketSs,
BackupQueryClients(appOpts, interfaceRegistry, feemarkettypes.NewQueryClient),
)

// Set authority to x/gov module account to only expect the module account to update params
Expand All @@ -496,6 +546,7 @@
tracer,
evmSs,
nil,
BackupQueryClients(appOpts, interfaceRegistry, evmtypes.NewQueryClient),
)

// register the proposal types
Expand Down
95 changes: 56 additions & 39 deletions server/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package config

import (
"encoding/json"
"errors"
"fmt"
"path"
Expand Down Expand Up @@ -179,6 +180,8 @@
FixRevertGasRefundHeight int64 `mapstructure:"fix-revert-gas-refund-height"`
// ReturnDataLimit defines maximum number of bytes returned from `eth_call` or similar invocations
ReturnDataLimit int64 `mapstructure:"return-data-limit"`
// A list of grpc address with block range
BackupGRPCBlockAddressBlockRange map[[2]int]string `mapstructure:"backup-grpc-address-block-range"`
}

// TLSConfig defines the certificate and matching private key for the server.
Expand Down Expand Up @@ -277,26 +280,27 @@
// DefaultJSONRPCConfig returns an EVM config with the JSON-RPC API enabled by default
func DefaultJSONRPCConfig() *JSONRPCConfig {
return &JSONRPCConfig{
Enable: true,
API: GetDefaultAPINamespaces(),
Address: DefaultJSONRPCAddress,
WsAddress: DefaultJSONRPCWsAddress,
GasCap: DefaultGasCap,
EVMTimeout: DefaultEVMTimeout,
TxFeeCap: DefaultTxFeeCap,
FilterCap: DefaultFilterCap,
FeeHistoryCap: DefaultFeeHistoryCap,
BlockRangeCap: DefaultBlockRangeCap,
LogsCap: DefaultLogsCap,
HTTPTimeout: DefaultHTTPTimeout,
HTTPIdleTimeout: DefaultHTTPIdleTimeout,
AllowUnprotectedTxs: DefaultAllowUnprotectedTxs,
MaxOpenConnections: DefaultMaxOpenConnections,
EnableIndexer: false,
AllowIndexerGap: true,
MetricsAddress: DefaultJSONRPCMetricsAddress,
FixRevertGasRefundHeight: DefaultFixRevertGasRefundHeight,
ReturnDataLimit: DefaultReturnDataLimit,
Enable: true,
API: GetDefaultAPINamespaces(),
Address: DefaultJSONRPCAddress,
WsAddress: DefaultJSONRPCWsAddress,
GasCap: DefaultGasCap,
EVMTimeout: DefaultEVMTimeout,
TxFeeCap: DefaultTxFeeCap,
FilterCap: DefaultFilterCap,
FeeHistoryCap: DefaultFeeHistoryCap,
BlockRangeCap: DefaultBlockRangeCap,
LogsCap: DefaultLogsCap,
HTTPTimeout: DefaultHTTPTimeout,
HTTPIdleTimeout: DefaultHTTPIdleTimeout,
AllowUnprotectedTxs: DefaultAllowUnprotectedTxs,
MaxOpenConnections: DefaultMaxOpenConnections,
EnableIndexer: false,
AllowIndexerGap: true,
MetricsAddress: DefaultJSONRPCMetricsAddress,
FixRevertGasRefundHeight: DefaultFixRevertGasRefundHeight,
ReturnDataLimit: DefaultReturnDataLimit,
BackupGRPCBlockAddressBlockRange: make(map[[2]int]string),
}
}

Expand Down Expand Up @@ -403,6 +407,18 @@
return Config{}, err
}

data := make(map[string][2]int)
raw := v.GetString("json-rpc.backup-grpc-address-block-range")
if len(raw) > 0 {
err = json.Unmarshal([]byte(raw), &data)
if err != nil {
return Config{}, err

Check warning on line 415 in server/config/config.go

View check run for this annotation

Codecov / codecov/patch

server/config/config.go#L410-L415

Added lines #L410 - L415 were not covered by tests
}
}
backupGRPCBlockAddressBlockRange := make(map[[2]int]string)
for k, v := range data {
backupGRPCBlockAddressBlockRange[v] = k

Check warning on line 420 in server/config/config.go

View check run for this annotation

Codecov / codecov/patch

server/config/config.go#L418-L420

Added lines #L418 - L420 were not covered by tests
}
Comment on lines +419 to +421

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
return Config{
Config: cfg,
EVM: EVMConfig{
Expand All @@ -412,25 +428,26 @@
BlockSTMWorkers: v.GetInt("evm.block-stm-workers"),
},
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"),
GasCap: v.GetUint64("json-rpc.gas-cap"),
FilterCap: v.GetInt32("json-rpc.filter-cap"),
FeeHistoryCap: v.GetInt32("json-rpc.feehistory-cap"),
TxFeeCap: v.GetFloat64("json-rpc.txfee-cap"),
EVMTimeout: v.GetDuration("json-rpc.evm-timeout"),
LogsCap: v.GetInt32("json-rpc.logs-cap"),
BlockRangeCap: v.GetInt32("json-rpc.block-range-cap"),
HTTPTimeout: v.GetDuration("json-rpc.http-timeout"),
HTTPIdleTimeout: v.GetDuration("json-rpc.http-idle-timeout"),
MaxOpenConnections: v.GetInt("json-rpc.max-open-connections"),
EnableIndexer: v.GetBool("json-rpc.enable-indexer"),
AllowIndexerGap: v.GetBool("json-rpc.allow-indexer-gap"),
MetricsAddress: v.GetString("json-rpc.metrics-address"),
FixRevertGasRefundHeight: v.GetInt64("json-rpc.fix-revert-gas-refund-height"),
ReturnDataLimit: v.GetInt64("json-rpc.return-data-limit"),
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"),
GasCap: v.GetUint64("json-rpc.gas-cap"),
FilterCap: v.GetInt32("json-rpc.filter-cap"),
FeeHistoryCap: v.GetInt32("json-rpc.feehistory-cap"),
TxFeeCap: v.GetFloat64("json-rpc.txfee-cap"),
EVMTimeout: v.GetDuration("json-rpc.evm-timeout"),
LogsCap: v.GetInt32("json-rpc.logs-cap"),
BlockRangeCap: v.GetInt32("json-rpc.block-range-cap"),
HTTPTimeout: v.GetDuration("json-rpc.http-timeout"),
HTTPIdleTimeout: v.GetDuration("json-rpc.http-idle-timeout"),
MaxOpenConnections: v.GetInt("json-rpc.max-open-connections"),
EnableIndexer: v.GetBool("json-rpc.enable-indexer"),
AllowIndexerGap: v.GetBool("json-rpc.allow-indexer-gap"),
MetricsAddress: v.GetString("json-rpc.metrics-address"),
FixRevertGasRefundHeight: v.GetInt64("json-rpc.fix-revert-gas-refund-height"),
ReturnDataLimit: v.GetInt64("json-rpc.return-data-limit"),
BackupGRPCBlockAddressBlockRange: backupGRPCBlockAddressBlockRange,

Check warning on line 450 in server/config/config.go

View check run for this annotation

Codecov / codecov/patch

server/config/config.go#L431-L450

Added lines #L431 - L450 were not covered by tests
},
TLS: TLSConfig{
CertificatePath: v.GetString("tls.certificate-path"),
Expand Down
5 changes: 5 additions & 0 deletions server/config/toml.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ fix-revert-gas-refund-height = {{ .JSONRPC.FixRevertGasRefundHeight }}
# Maximum number of bytes returned from eth_call or similar invocations.
return-data-limit = {{ .JSONRPC.ReturnDataLimit }}

# A list of backup grpc address with block range
# Example: "0.0.0.0:26113" = [0, 20]
backup-grpc-address-block-range = "{{ "{" }}{{ range $k, $v := .JSONRPC.BackupGRPCBlockAddressBlockRange }}" +
"\"{{ $v }}\": [{{index $k 0 }}, {{ index $k 1}}]{{ end }}{{ "}" }}"

###############################################################################
### TLS Configuration ###
###############################################################################
Expand Down
7 changes: 4 additions & 3 deletions server/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,10 @@ const (
// JSONRPCEnableMetrics enables EVM RPC metrics server.
// Set to `metrics` which is hardcoded flag from go-ethereum.
// https://github.com/ethereum/go-ethereum/blob/master/metrics/metrics.go#L35-L55
JSONRPCEnableMetrics = "metrics"
JSONRPCFixRevertGasRefundHeight = "json-rpc.fix-revert-gas-refund-height"
JSONRPCReturnDataLimit = "json-rpc.return-data-limit"
JSONRPCEnableMetrics = "metrics"
JSONRPCFixRevertGasRefundHeight = "json-rpc.fix-revert-gas-refund-height"
JSONRPCReturnDataLimit = "json-rpc.return-data-limit"
JSONRPCBackupGRPCBlockAddressBlockRange = "json-rpc.backup-grpc-address-block-range"
)

// EVM flags
Expand Down
1 change: 1 addition & 0 deletions server/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ which accepts a path for the resulting pprof file.
cmd.Flags().Bool(srvflags.JSONRPCEnableIndexer, false, "Enable the custom tx indexer for json-rpc")
cmd.Flags().Bool(srvflags.JSONRPCAllowIndexerGap, true, "Allow block gap for the custom tx indexer for json-rpc")
cmd.Flags().Bool(srvflags.JSONRPCEnableMetrics, false, "Define if EVM rpc metrics server should be enabled")
cmd.Flags().String(srvflags.JSONRPCBackupGRPCBlockAddressBlockRange, "", "Define if backup grpc and block range is available")

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)") //nolint:lll
cmd.Flags().Uint64(srvflags.EVMMaxTxGasWanted, config.DefaultMaxTxGasWanted, "the gas wanted for each eth tx returned in ante handler in check tx mode") //nolint:lll
Expand Down
10 changes: 10 additions & 0 deletions server/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package server

import (
"context"
"fmt"
"net"
"net/http"
"os"
Expand All @@ -34,6 +35,7 @@ import (
"github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/version"

errorsmod "cosmossdk.io/errors"
tmlog "cosmossdk.io/log"
cmtcmd "github.com/cometbft/cometbft/cmd/cometbft/commands"
)
Expand Down Expand Up @@ -76,6 +78,14 @@ func AddCommands(
)
}

func ParseGRPCAddress(address string) (string, error) {
_, port, err := net.SplitHostPort(address)
if err != nil {
return "", errorsmod.Wrapf(err, "invalid grpc address %s", address)
}
return fmt.Sprintf("127.0.0.1:%s", port), nil
}

func MountGRPCWebServices(
router *mux.Router,
grpcWeb *grpcweb.WrappedGrpcServer,
Expand Down
21 changes: 17 additions & 4 deletions x/evm/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,16 @@

sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
ethparams "github.com/ethereum/go-ethereum/params"

rpctypes "github.com/evmos/ethermint/rpc/types"
ethermint "github.com/evmos/ethermint/types"
"github.com/evmos/ethermint/x/evm/types"
"github.com/evmos/ethermint/x/utils"
)

var _ types.QueryServer = Keeper{}
Expand Down Expand Up @@ -219,10 +218,24 @@
}

// Params implements the Query/Params gRPC method
func (k Keeper) Params(c context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
func (k Keeper) Params(c context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
// grpc
height, err := utils.GetHeightFromMetadata(c)
if err != nil {
return nil, err

Check warning on line 226 in x/evm/keeper/grpc_query.go

View check run for this annotation

Codecov / codecov/patch

x/evm/keeper/grpc_query.go#L226

Added line #L226 was not covered by tests
}
// cli
if height == 0 {
height = ctx.BlockHeight()
}
for blocks, client := range k.backupQueryClients {
if int64(blocks[0]) <= height && int64(blocks[1]) >= height {
params, err := client.Params(c, req)
return params, err

Check warning on line 235 in x/evm/keeper/grpc_query.go

View check run for this annotation

Codecov / codecov/patch

x/evm/keeper/grpc_query.go#L233-L235

Added lines #L233 - L235 were not covered by tests
}
}
Comment on lines +232 to +237

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
params := k.GetParams(ctx)

return &types.QueryParamsResponse{
Params: params,
}, nil
Expand Down
29 changes: 16 additions & 13 deletions x/evm/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@ type Keeper struct {
hooks types.EvmHooks

// Legacy subspace
ss paramstypes.Subspace
customContractFns []CustomContractFn
ss paramstypes.Subspace
customContractFns []CustomContractFn
backupQueryClients map[[2]int]types.QueryClient
}

// NewKeeper generates new evm module keeper
Expand All @@ -87,6 +88,7 @@ func NewKeeper(
tracer string,
ss paramstypes.Subspace,
customContractFns []CustomContractFn,
backupQueryClients map[[2]int]types.QueryClient,
) *Keeper {
// ensure evm module account is set
if addr := ak.GetModuleAddress(types.ModuleName); addr == nil {
Expand All @@ -100,17 +102,18 @@ func NewKeeper(

// NOTE: we pass in the parameter space to the CommitStateDB in order to use custom denominations for the EVM operations
return &Keeper{
cdc: cdc,
authority: authority,
accountKeeper: ak,
bankKeeper: bankKeeper,
stakingKeeper: sk,
feeMarketKeeper: fmk,
storeKey: storeKey,
objectKey: objectKey,
tracer: tracer,
ss: ss,
customContractFns: customContractFns,
cdc: cdc,
authority: authority,
accountKeeper: ak,
bankKeeper: bankKeeper,
stakingKeeper: sk,
feeMarketKeeper: fmk,
storeKey: storeKey,
objectKey: objectKey,
tracer: tracer,
ss: ss,
customContractFns: customContractFns,
backupQueryClients: backupQueryClients,
}
}

Expand Down
1 change: 1 addition & 0 deletions x/evm/statedb/statedb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,7 @@ func newTestKeeper(t *testing.T, cms storetypes.MultiStore) (sdk.Context, *evmke
"",
paramstypes.Subspace{},
nil,
nil,
)

ctx := sdk.NewContext(cms, tmproto.Header{}, false, log.NewNopLogger())
Expand Down
Loading
Loading