laconicd/server/config/config.go
Jongwhan Lee 392d1dd8cf
rpc: eth_feeHistory (#734)
* Problem: missing json rpc of eth_feeHistory #685

add oracle backend

space ready

structure ok

refactoring

return feehistory

data flow ok

basefee

set gas used ratio

computing reward

add testing

add gas used

prepare data

fill reward

increase coin

fixing api

add mac

add launch

gas used ratio ok

print element

reward workes

reward working

fix panic

value correct

remove debugging log

tidy up

tidy up

remove oracle

tidy up

fix handler crash

add unit test

tidy up

add limit check

reformat

fix lint

fix lint

fix lint

fix lint

Update rpc/ethereum/backend/feebackend.go

thanks

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

Update rpc/ethereum/backend/feebackend.go

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

Update rpc/ethereum/backend/feebackend.go

thanks

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

Update rpc/ethereum/backend/feebackend.go

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

fix compile error

split lines

remove temporary string conversion

return error if gaslimit is 0

move OneFeeHistory to types

add comment

only err check

Update rpc/ethereum/backend/feebackend.go

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

Update rpc/ethereum/backend/feebackend.go

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

tidy up

add feehistory-cap

* Apply suggestions from code review

* changelog

Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
Co-authored-by: Federico Kunze Küllmer <federico.kunze94@gmail.com>
2021-11-17 11:58:52 +00:00

284 lines
8.5 KiB
Go

package config
import (
"errors"
"fmt"
"path"
"time"
"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"
// DefaultJSONRPCAddress is the default address the JSON-RPC server binds to.
DefaultJSONRPCAddress = "0.0.0.0:8545"
// 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 = ""
DefaultGasCap uint64 = 25000000
DefaultFilterCap int32 = 200
DefaultFeeHistoryCap int32 = 100
DefaultEVMTimeout = 5 * time.Second
// default 1.0 eth
DefaultTxFeeCap float64 = 1.0
)
var evmTracers = []string{"json", "markdown", "struct", "access_list"}
// Config defines the server's top level configuration. It includes the default app config
// from the SDK as well as the EVM configuration to enable the JSON-RPC APIs.
type Config struct {
config.Config
EVM EVMConfig `mapstructure:"evm"`
JSONRPC JSONRPCConfig `mapstructure:"json-rpc"`
TLS TLSConfig `mapstructure:"tls"`
}
// 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"`
}
// JSONRPCConfig defines configuration for the EVM RPC server.
type JSONRPCConfig struct {
// API defines a list of JSON-RPC namespaces that should be enabled
API []string `mapstructure:"api"`
// 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"`
// GasCap is the global gas cap for eth-call variants.
GasCap uint64 `mapstructure:"gas-cap"`
// EVMTimeout is the global timeout for eth-call.
EVMTimeout time.Duration `mapstructure:"evm-timeout"`
// TxFeeCap is the global tx-fee cap for send transaction
TxFeeCap float64 `mapstructure:"txfee-cap"`
// FilterCap is the global cap for total number of filters that can be created.
FilterCap int32 `mapstructure:"filter-cap"`
// FeeHistoryCap is the global cap for total number of blocks that can be fetched
FeeHistoryCap int32 `mapstructure:"feehistory-cap"`
// Enable defines if the EVM RPC server should be enabled.
Enable bool `mapstructure:"enable"`
}
// TLSConfig defines the certificate and matching private key for the server.
type TLSConfig struct {
// CertificatePath the file path for the certificate .pem file
CertificatePath string `mapstructure:"certificate-path"`
// KeyPath the file path for the key .pem file
KeyPath string `mapstructure:"key-path"`
}
// AppConfig helps to override default appConfig template and configs.
// return "", nil if no custom configuration is required for the application.
func AppConfig(denom string) (string, interface{}) {
// Optionally allow the chain developer to overwrite the SDK's default
// server config.
srvCfg := config.DefaultConfig()
// The SDK's default minimum gas price is set to "" (empty value) inside
// app.toml. If left empty by validators, the node will halt on startup.
// However, the chain developer can set a default app.toml value for their
// validators here.
//
// In summary:
// - if you leave srvCfg.MinGasPrices = "", all validators MUST tweak their
// own app.toml config,
// - if you set srvCfg.MinGasPrices non-empty, validators CAN tweak their
// own app.toml to override, or use this default value.
//
// In ethermint, we set the min gas prices to 0.
if denom != "" {
srvCfg.MinGasPrices = "0" + denom
}
customAppConfig := Config{
Config: *srvCfg,
EVM: *DefaultEVMConfig(),
JSONRPC: *DefaultJSONRPCConfig(),
TLS: *DefaultTLSConfig(),
}
customAppTemplate := config.DefaultConfigTemplate + DefaultConfigTemplate
return customAppTemplate, customAppConfig
}
// DefaultConfig returns server's default configuration.
func DefaultConfig() *Config {
return &Config{
Config: *config.DefaultConfig(),
EVM: *DefaultEVMConfig(),
JSONRPC: *DefaultJSONRPCConfig(),
TLS: *DefaultTLSConfig(),
}
}
// 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 c.Tracer != "" && !strings.StringInSlice(c.Tracer, evmTracers) {
return fmt.Errorf("invalid tracer type %s, available types: %v", c.Tracer, evmTracers)
}
return nil
}
// GetDefaultAPINamespaces returns the default list of JSON-RPC namespaces that should be enabled
func GetDefaultAPINamespaces() []string {
return []string{"eth", "net", "web3"}
}
// 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,
}
}
// Validate returns an error if the JSON-RPC configuration fields are invalid.
func (c JSONRPCConfig) Validate() error {
if c.Enable && len(c.API) == 0 {
return errors.New("cannot enable JSON-RPC without defining any API namespace")
}
if c.FilterCap < 0 {
return errors.New("JSON-RPC filter-cap cannot be negative")
}
if c.FeeHistoryCap <= 0 {
return errors.New("JSON-RPC feehistory-cap cannot be negative or 0")
}
if c.TxFeeCap < 0 {
return errors.New("JSON-RPC tx fee cap cannot be negative")
}
if c.EVMTimeout < 0 {
return errors.New("JSON-RPC EVM timeout duration cannot be negative")
}
// TODO: validate APIs
seenAPIs := make(map[string]bool)
for _, api := range c.API {
if seenAPIs[api] {
return fmt.Errorf("repeated API namespace '%s'", api)
}
seenAPIs[api] = true
}
return nil
}
// DefaultTLSConfig returns the default TLS configuration
func DefaultTLSConfig() *TLSConfig {
return &TLSConfig{
CertificatePath: "",
KeyPath: "",
}
}
// Validate returns an error if the TLS certificate and key file extensions are invalid.
func (c TLSConfig) Validate() error {
certExt := path.Ext(c.CertificatePath)
if c.CertificatePath != "" && certExt != ".pem" {
return fmt.Errorf("invalid extension %s for certificate path %s, expected '.pem'", certExt, c.CertificatePath)
}
keyExt := path.Ext(c.KeyPath)
if c.KeyPath != "" && keyExt != ".pem" {
return fmt.Errorf("invalid extension %s for key path %s, expected '.pem'", keyExt, c.KeyPath)
}
return nil
}
// GetConfig returns a fully parsed Config object.
func GetConfig(v *viper.Viper) Config {
cfg := config.GetConfig(v)
return Config{
Config: cfg,
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"),
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"),
},
TLS: TLSConfig{
CertificatePath: v.GetString("tls.certificate-path"),
KeyPath: v.GetString("tls.key-path"),
},
}
}
// ParseConfig retrieves the default environment configuration for the
// application.
func ParseConfig(v *viper.Viper) (*Config, error) {
conf := DefaultConfig()
err := v.Unmarshal(conf)
return conf, err
}
// 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())
}
if err := c.JSONRPC.Validate(); err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrAppConfig, "invalid json-rpc config value: %s", err.Error())
}
if err := c.TLS.Validate(); err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrAppConfig, "invalid tls config value: %s", err.Error())
}
return c.Config.ValidateBasic()
}