From 6b0e71539add0aa34a0398ac1d00ba3fe1545fbb Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Thu, 20 Jun 2024 18:43:20 +0200 Subject: [PATCH] go: Fix more linter problems (#228) --- .golangci.yml | 17 ++- cmd/soroban-rpc/internal/config/flags.go | 141 +++++++++--------- .../internal/config/{config.go => main.go} | 2 +- .../config/{config_test.go => main_test.go} | 0 .../config/{config_option.go => option.go} | 55 ++++--- .../{config_option_test.go => option_test.go} | 24 +-- cmd/soroban-rpc/internal/config/options.go | 42 +++--- .../internal/config/options_test.go | 14 +- cmd/soroban-rpc/internal/config/parse.go | 20 ++- cmd/soroban-rpc/internal/config/toml_test.go | 3 +- cmd/soroban-rpc/internal/config/version.go | 1 + cmd/soroban-rpc/internal/daemon/daemon.go | 18 ++- .../internal/daemon/interfaces/noOpDaemon.go | 12 +- cmd/soroban-rpc/internal/db/db.go | 6 +- cmd/soroban-rpc/internal/db/ledger_test.go | 6 +- cmd/soroban-rpc/internal/db/ledgerentry.go | 8 +- .../internal/db/ledgerentry_test.go | 2 +- cmd/soroban-rpc/internal/db/migration.go | 1 - cmd/soroban-rpc/internal/db/transaction.go | 38 +++-- .../internal/db/transaction_test.go | 6 +- cmd/soroban-rpc/internal/events/cursor.go | 8 +- .../internal/events/events_test.go | 3 +- .../internal/feewindow/feewindow.go | 7 +- .../internal/feewindow/feewindow_test.go | 19 ++- .../internal/ingest/service_test.go | 5 +- .../integrationtest/get_fee_stats_test.go | 5 +- .../integrationtest/get_transactions_test.go | 9 +- .../integrationtest/get_version_info_test.go | 5 +- .../integrationtest/infrastructure/client.go | 7 +- .../infrastructure/contract.go | 3 +- .../integrationtest/infrastructure/test.go | 9 +- .../integrationtest/infrastructure/util.go | 16 +- .../internal/integrationtest/metrics_test.go | 8 +- .../internal/integrationtest/migrate_test.go | 4 +- .../integrationtest/transaction_test.go | 6 +- .../internal/integrationtest/upgrade_test.go | 3 +- cmd/soroban-rpc/internal/jsonrpc.go | 2 +- .../internal/methods/get_events.go | 4 +- .../methods/get_latest_ledger_test.go | 12 +- .../internal/methods/get_ledger_entries.go | 7 +- .../internal/methods/get_ledger_entry.go | 2 +- .../internal/methods/get_transaction_test.go | 1 - .../internal/methods/get_transactions.go | 10 +- .../internal/methods/get_transactions_test.go | 44 +++--- .../internal/methods/simulate_transaction.go | 12 +- .../methods/simulate_transaction_test.go | 3 +- cmd/soroban-rpc/internal/network/backlogQ.go | 17 +-- .../internal/network/backlogQ_test.go | 4 +- .../network/requestdurationlimiter.go | 3 + .../network/requestdurationlimiter_test.go | 5 +- .../internal/network/utils_test.go | 5 + cmd/soroban-rpc/internal/preflight/pool.go | 54 ++++--- .../internal/preflight/preflight.go | 14 +- .../internal/preflight/preflight_test.go | 19 ++- .../internal/util/panicgroup_test.go | 7 +- cmd/soroban-rpc/main.go | 2 + 56 files changed, 409 insertions(+), 351 deletions(-) rename cmd/soroban-rpc/internal/config/{config.go => main.go} (99%) rename cmd/soroban-rpc/internal/config/{config_test.go => main_test.go} (100%) rename cmd/soroban-rpc/internal/config/{config_option.go => option.go} (61%) rename cmd/soroban-rpc/internal/config/{config_option_test.go => option_test.go} (91%) diff --git a/.golangci.yml b/.golangci.yml index aca3ea8a..dcdfcad4 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -87,8 +87,10 @@ linters-settings: linters: enable-all: true disable: + # deprecated: - gomnd - execinquery + - depguard - nlreturn - godox @@ -101,23 +103,22 @@ linters: - wsl - wrapcheck - testpackage - # TODO: I didn't manage to make it accept short parameter names + # TODO: varnamelen: I didn't manage to make it accept short parameter names - varnamelen - # TODO: consider enabling it later on + # TODO: ireturn: consider enabling it later on - ireturn - godot presets: [ ] fast: false issues: - # Excluding configuration per-path, per-linter, per-text and per-source + # Exclude certain checks in test files exclude-rules: - - path: _test\.go - linters: - - gosec - - path: cmd/soroban-rpc/internal/integrationtest/infrastructure/ + - path: '^(.*_test\.go|cmd/soroban-rpc/internal/integrationtest/infrastructure/.*)$' linters: + - mnd - gosec - + - gochecknoglobals + - nosprintfhostport run: timeout: 10m diff --git a/cmd/soroban-rpc/internal/config/flags.go b/cmd/soroban-rpc/internal/config/flags.go index d313aa31..0c313460 100644 --- a/cmd/soroban-rpc/internal/config/flags.go +++ b/cmd/soroban-rpc/internal/config/flags.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert // this file uses several unchecked assertions package config import ( @@ -22,151 +23,153 @@ func (cfg *Config) AddFlags(cmd *cobra.Command) error { } // AddFlag adds a CLI flag for this option to the given flagset. -func (co *ConfigOption) AddFlag(flagset *pflag.FlagSet) error { +// +//nolint:funlen,cyclop +func (o *Option) AddFlag(flagset *pflag.FlagSet) error { // config options that has no names do not represent a valid flag. - if len(co.Name) == 0 { + if len(o.Name) == 0 { return nil } // Treat any option with a custom parser as a string option. - if co.CustomSetValue != nil { - if co.DefaultValue == nil { - co.DefaultValue = "" + if o.CustomSetValue != nil { + if o.DefaultValue == nil { + o.DefaultValue = "" } - flagset.String(co.Name, fmt.Sprint(co.DefaultValue), co.UsageText()) - co.flag = flagset.Lookup(co.Name) + flagset.String(o.Name, fmt.Sprint(o.DefaultValue), o.UsageText()) + o.flag = flagset.Lookup(o.Name) return nil } // Infer the type of the flag based on the type of the ConfigKey. This list // of options is based on the available flag types from pflags - switch co.ConfigKey.(type) { + switch o.ConfigKey.(type) { case *bool: - flagset.Bool(co.Name, co.DefaultValue.(bool), co.UsageText()) + flagset.Bool(o.Name, o.DefaultValue.(bool), o.UsageText()) case *time.Duration: - flagset.Duration(co.Name, co.DefaultValue.(time.Duration), co.UsageText()) + flagset.Duration(o.Name, o.DefaultValue.(time.Duration), o.UsageText()) case *float32: - flagset.Float32(co.Name, co.DefaultValue.(float32), co.UsageText()) + flagset.Float32(o.Name, o.DefaultValue.(float32), o.UsageText()) case *float64: - flagset.Float64(co.Name, co.DefaultValue.(float64), co.UsageText()) + flagset.Float64(o.Name, o.DefaultValue.(float64), o.UsageText()) case *net.IP: - flagset.IP(co.Name, co.DefaultValue.(net.IP), co.UsageText()) + flagset.IP(o.Name, o.DefaultValue.(net.IP), o.UsageText()) case *net.IPNet: - flagset.IPNet(co.Name, co.DefaultValue.(net.IPNet), co.UsageText()) + flagset.IPNet(o.Name, o.DefaultValue.(net.IPNet), o.UsageText()) case *int: - flagset.Int(co.Name, co.DefaultValue.(int), co.UsageText()) + flagset.Int(o.Name, o.DefaultValue.(int), o.UsageText()) case *int8: - flagset.Int8(co.Name, co.DefaultValue.(int8), co.UsageText()) + flagset.Int8(o.Name, o.DefaultValue.(int8), o.UsageText()) case *int16: - flagset.Int16(co.Name, co.DefaultValue.(int16), co.UsageText()) + flagset.Int16(o.Name, o.DefaultValue.(int16), o.UsageText()) case *int32: - flagset.Int32(co.Name, co.DefaultValue.(int32), co.UsageText()) + flagset.Int32(o.Name, o.DefaultValue.(int32), o.UsageText()) case *int64: - flagset.Int64(co.Name, co.DefaultValue.(int64), co.UsageText()) + flagset.Int64(o.Name, o.DefaultValue.(int64), o.UsageText()) case *[]int: - flagset.IntSlice(co.Name, co.DefaultValue.([]int), co.UsageText()) + flagset.IntSlice(o.Name, o.DefaultValue.([]int), o.UsageText()) case *[]int32: - flagset.Int32Slice(co.Name, co.DefaultValue.([]int32), co.UsageText()) + flagset.Int32Slice(o.Name, o.DefaultValue.([]int32), o.UsageText()) case *[]int64: - flagset.Int64Slice(co.Name, co.DefaultValue.([]int64), co.UsageText()) + flagset.Int64Slice(o.Name, o.DefaultValue.([]int64), o.UsageText()) case *string: // Set an empty string if no default was provided, since some value is always required for pflags - if co.DefaultValue == nil { - co.DefaultValue = "" + if o.DefaultValue == nil { + o.DefaultValue = "" } - flagset.String(co.Name, co.DefaultValue.(string), co.UsageText()) + flagset.String(o.Name, o.DefaultValue.(string), o.UsageText()) case *[]string: // Set an empty string if no default was provided, since some value is always required for pflags - if co.DefaultValue == nil { - co.DefaultValue = []string{} + if o.DefaultValue == nil { + o.DefaultValue = []string{} } - flagset.StringSlice(co.Name, co.DefaultValue.([]string), co.UsageText()) + flagset.StringSlice(o.Name, o.DefaultValue.([]string), o.UsageText()) case *uint: - flagset.Uint(co.Name, co.DefaultValue.(uint), co.UsageText()) + flagset.Uint(o.Name, o.DefaultValue.(uint), o.UsageText()) case *uint8: - flagset.Uint8(co.Name, co.DefaultValue.(uint8), co.UsageText()) + flagset.Uint8(o.Name, o.DefaultValue.(uint8), o.UsageText()) case *uint16: - flagset.Uint16(co.Name, co.DefaultValue.(uint16), co.UsageText()) + flagset.Uint16(o.Name, o.DefaultValue.(uint16), o.UsageText()) case *uint32: - flagset.Uint32(co.Name, co.DefaultValue.(uint32), co.UsageText()) + flagset.Uint32(o.Name, o.DefaultValue.(uint32), o.UsageText()) case *uint64: - flagset.Uint64(co.Name, co.DefaultValue.(uint64), co.UsageText()) + flagset.Uint64(o.Name, o.DefaultValue.(uint64), o.UsageText()) case *[]uint: - flagset.UintSlice(co.Name, co.DefaultValue.([]uint), co.UsageText()) + flagset.UintSlice(o.Name, o.DefaultValue.([]uint), o.UsageText()) default: - return fmt.Errorf("unexpected option type: %T", co.ConfigKey) + return fmt.Errorf("unexpected option type: %T", o.ConfigKey) } - co.flag = flagset.Lookup(co.Name) + o.flag = flagset.Lookup(o.Name) return nil } -func (co *ConfigOption) GetFlag(flagset *pflag.FlagSet) (interface{}, error) { +//nolint:cyclop +func (o *Option) GetFlag(flagset *pflag.FlagSet) (interface{}, error) { // Treat any option with a custom parser as a string option. - if co.CustomSetValue != nil { - return flagset.GetString(co.Name) + if o.CustomSetValue != nil { + return flagset.GetString(o.Name) } // Infer the type of the flag based on the type of the ConfigKey. This list // of options is based on the available flag types from pflags, and must // match the above in `AddFlag`. - switch co.ConfigKey.(type) { + switch o.ConfigKey.(type) { case *bool: - return flagset.GetBool(co.Name) + return flagset.GetBool(o.Name) case *time.Duration: - return flagset.GetDuration(co.Name) + return flagset.GetDuration(o.Name) case *float32: - return flagset.GetFloat32(co.Name) + return flagset.GetFloat32(o.Name) case *float64: - return flagset.GetFloat64(co.Name) + return flagset.GetFloat64(o.Name) case *net.IP: - return flagset.GetIP(co.Name) + return flagset.GetIP(o.Name) case *net.IPNet: - return flagset.GetIPNet(co.Name) + return flagset.GetIPNet(o.Name) case *int: - return flagset.GetInt(co.Name) + return flagset.GetInt(o.Name) case *int8: - return flagset.GetInt8(co.Name) + return flagset.GetInt8(o.Name) case *int16: - return flagset.GetInt16(co.Name) + return flagset.GetInt16(o.Name) case *int32: - return flagset.GetInt32(co.Name) + return flagset.GetInt32(o.Name) case *int64: - return flagset.GetInt64(co.Name) + return flagset.GetInt64(o.Name) case *[]int: - return flagset.GetIntSlice(co.Name) + return flagset.GetIntSlice(o.Name) case *[]int32: - return flagset.GetInt32Slice(co.Name) + return flagset.GetInt32Slice(o.Name) case *[]int64: - return flagset.GetInt64Slice(co.Name) + return flagset.GetInt64Slice(o.Name) case *string: - return flagset.GetString(co.Name) + return flagset.GetString(o.Name) case *[]string: - return flagset.GetStringSlice(co.Name) + return flagset.GetStringSlice(o.Name) case *uint: - return flagset.GetUint(co.Name) + return flagset.GetUint(o.Name) case *uint8: - return flagset.GetUint8(co.Name) + return flagset.GetUint8(o.Name) case *uint16: - return flagset.GetUint16(co.Name) + return flagset.GetUint16(o.Name) case *uint32: - return flagset.GetUint32(co.Name) + return flagset.GetUint32(o.Name) case *uint64: - return flagset.GetUint64(co.Name) + return flagset.GetUint64(o.Name) case *[]uint: - return flagset.GetUintSlice(co.Name) + return flagset.GetUintSlice(o.Name) default: - return nil, fmt.Errorf("unexpected option type: %T", co.ConfigKey) + return nil, fmt.Errorf("unexpected option type: %T", o.ConfigKey) } } // UsageText returns the string to use for the usage text of the option. The -// string returned will be the Usage defined on the ConfigOption, along with +// string returned will be the Usage defined on the Option, along with // the environment variable. -func (co *ConfigOption) UsageText() string { - envVar, hasEnvVar := co.getEnvKey() +func (o *Option) UsageText() string { + envVar, hasEnvVar := o.getEnvKey() if hasEnvVar { - return fmt.Sprintf("%s (%s)", co.Usage, envVar) - } else { - return co.Usage + return fmt.Sprintf("%s (%s)", o.Usage, envVar) } + return o.Usage } diff --git a/cmd/soroban-rpc/internal/config/config.go b/cmd/soroban-rpc/internal/config/main.go similarity index 99% rename from cmd/soroban-rpc/internal/config/config.go rename to cmd/soroban-rpc/internal/config/main.go index 2ce48459..1321feb6 100644 --- a/cmd/soroban-rpc/internal/config/config.go +++ b/cmd/soroban-rpc/internal/config/main.go @@ -71,7 +71,7 @@ type Config struct { MaxGetFeeStatsExecutionDuration time.Duration // We memoize these, so they bind to pflags correctly - optionsCache *ConfigOptions + optionsCache *Options flagset *pflag.FlagSet } diff --git a/cmd/soroban-rpc/internal/config/config_test.go b/cmd/soroban-rpc/internal/config/main_test.go similarity index 100% rename from cmd/soroban-rpc/internal/config/config_test.go rename to cmd/soroban-rpc/internal/config/main_test.go diff --git a/cmd/soroban-rpc/internal/config/config_option.go b/cmd/soroban-rpc/internal/config/option.go similarity index 61% rename from cmd/soroban-rpc/internal/config/config_option.go rename to cmd/soroban-rpc/internal/config/option.go index ffbdc936..2583a383 100644 --- a/cmd/soroban-rpc/internal/config/config_option.go +++ b/cmd/soroban-rpc/internal/config/option.go @@ -12,21 +12,22 @@ import ( "github.com/stellar/go/support/strutils" ) -// ConfigOptions is a group of ConfigOptions that can be for convenience +// Options is a group of Options that can be for convenience // initialized and set at the same time. -type ConfigOptions []*ConfigOption +type Options []*Option // Validate all the config options. -func (options ConfigOptions) Validate() error { - var missingOptions []errMissingRequiredOption +func (options Options) Validate() error { + var missingOptions []missingRequiredOptionError for _, option := range options { if option.Validate != nil { err := option.Validate(option) if err == nil { continue } - if missingOption, ok := err.(errMissingRequiredOption); ok { - missingOptions = append(missingOptions, missingOption) + var missingOptionErr missingRequiredOptionError + if ok := errors.As(err, &missingOptionErr); ok { + missingOptions = append(missingOptions, missingOptionErr) continue } return errors.New("Invalid config value for " + option.Name) @@ -39,28 +40,36 @@ func (options ConfigOptions) Validate() error { errString += "\n*\t" + missingOpt.strErr errString += "\n \t" + missingOpt.usage } - return &errMissingRequiredOption{strErr: errString} + return &missingRequiredOptionError{strErr: errString} } return nil } -// ConfigOption is a complete description of the configuration of a command line option -type ConfigOption struct { - Name string // e.g. "database-url" - EnvVar string // e.g. "DATABASE_URL". Defaults to uppercase/underscore representation of name - TomlKey string // e.g. "DATABASE_URL". Defaults to uppercase/underscore representation of name. - to omit from toml - Usage string // Help text - DefaultValue interface{} // A default if no option is provided. Omit or set to `nil` if no default - ConfigKey interface{} // Pointer to the final key in the linked Config struct - CustomSetValue func(*ConfigOption, interface{}) error // Optional function for custom validation/transformation - Validate func(*ConfigOption) error // Function called after loading all options, to validate the configuration - MarshalTOML func(*ConfigOption) (interface{}, error) +// Option is a complete description of the configuration of a command line option +type Option struct { + // e.g. "database-url" + Name string + // e.g. "DATABASE_URL".Defaults to uppercase/underscore representation of name + EnvVar string + // e.g. "DATABASE_URL". Defaults to uppercase/underscore representation of name. - to omit from toml + TomlKey string + // Help text + Usage string + // A default if no option is provided. Omit or set to `nil` if no default + DefaultValue interface{} + // Pointer to the final key in the linked Config struct + ConfigKey interface{} + // Optional function for custom validation/transformation + CustomSetValue func(*Option, interface{}) error + // Function called after loading all options, to validate the configuration + Validate func(*Option) error + MarshalTOML func(*Option) (interface{}, error) flag *pflag.Flag // The persistent flag that the config option is attached to } // Returns false if this option is omitted in the toml -func (o ConfigOption) getTomlKey() (string, bool) { +func (o Option) getTomlKey() (string, bool) { if o.TomlKey == "-" || o.TomlKey == "_" { return "", false } @@ -74,7 +83,7 @@ func (o ConfigOption) getTomlKey() (string, bool) { } // Returns false if this option is omitted in the env -func (o ConfigOption) getEnvKey() (string, bool) { +func (o Option) getEnvKey() (string, bool) { if o.EnvVar == "-" || o.EnvVar == "_" { return "", false } @@ -85,7 +94,7 @@ func (o ConfigOption) getEnvKey() (string, bool) { } // TODO: See if we can remove CustomSetValue into just SetValue/ParseValue -func (o *ConfigOption) setValue(i interface{}) (err error) { +func (o *Option) setValue(i interface{}) (err error) { if o.CustomSetValue != nil { return o.CustomSetValue(o, i) } @@ -99,7 +108,7 @@ func (o *ConfigOption) setValue(i interface{}) (err error) { err = fmt.Errorf("config option setting error ('%s') %v", o.Name, recoverRes) } }() - parser := func(option *ConfigOption, i interface{}) error { + parser := func(_ *Option, _ interface{}) error { return fmt.Errorf("no parser for flag %s", o.Name) } switch o.ConfigKey.(type) { @@ -124,7 +133,7 @@ func (o *ConfigOption) setValue(i interface{}) (err error) { return parser(o, i) } -func (o *ConfigOption) marshalTOML() (interface{}, error) { +func (o *Option) marshalTOML() (interface{}, error) { if o.MarshalTOML != nil { return o.MarshalTOML(o) } diff --git a/cmd/soroban-rpc/internal/config/config_option_test.go b/cmd/soroban-rpc/internal/config/option_test.go similarity index 91% rename from cmd/soroban-rpc/internal/config/config_option_test.go rename to cmd/soroban-rpc/internal/config/option_test.go index a6309cb3..83e9b5eb 100644 --- a/cmd/soroban-rpc/internal/config/config_option_test.go +++ b/cmd/soroban-rpc/internal/config/option_test.go @@ -12,39 +12,39 @@ import ( func TestConfigOptionGetTomlKey(t *testing.T) { // Explicitly set toml key - key, ok := ConfigOption{TomlKey: "TOML_KEY"}.getTomlKey() + key, ok := Option{TomlKey: "TOML_KEY"}.getTomlKey() assert.Equal(t, "TOML_KEY", key) assert.True(t, ok) // Explicitly disabled toml key via `-` - key, ok = ConfigOption{TomlKey: "-"}.getTomlKey() + key, ok = Option{TomlKey: "-"}.getTomlKey() assert.Equal(t, "", key) assert.False(t, ok) // Explicitly disabled toml key via `_` - key, ok = ConfigOption{TomlKey: "_"}.getTomlKey() + key, ok = Option{TomlKey: "_"}.getTomlKey() assert.Equal(t, "", key) assert.False(t, ok) // Fallback to env var - key, ok = ConfigOption{EnvVar: "ENV_VAR"}.getTomlKey() + key, ok = Option{EnvVar: "ENV_VAR"}.getTomlKey() assert.Equal(t, "ENV_VAR", key) assert.True(t, ok) // Env-var disabled, autogenerate from name - key, ok = ConfigOption{Name: "test-flag", EnvVar: "-"}.getTomlKey() + key, ok = Option{Name: "test-flag", EnvVar: "-"}.getTomlKey() assert.Equal(t, "TEST_FLAG", key) assert.True(t, ok) // Env-var not set, autogenerate from name - key, ok = ConfigOption{Name: "test-flag"}.getTomlKey() + key, ok = Option{Name: "test-flag"}.getTomlKey() assert.Equal(t, "TEST_FLAG", key) assert.True(t, ok) } func TestValidateRequired(t *testing.T) { var strVal string - o := &ConfigOption{ + o := &Option{ Name: "required-option", ConfigKey: &strVal, Validate: required, @@ -64,7 +64,7 @@ func TestValidateRequired(t *testing.T) { func TestValidatePositiveUint32(t *testing.T) { var val uint32 - o := &ConfigOption{ + o := &Option{ Name: "positive-option", ConfigKey: &val, Validate: positive, @@ -84,7 +84,7 @@ func TestValidatePositiveUint32(t *testing.T) { func TestValidatePositiveInt(t *testing.T) { var val int - o := &ConfigOption{ + o := &Option{ Name: "positive-option", ConfigKey: &val, Validate: positive, @@ -107,7 +107,7 @@ func TestValidatePositiveInt(t *testing.T) { } func TestUnassignableField(t *testing.T) { - var co ConfigOption + var co Option var b bool co.Name = "mykey" co.ConfigKey = &b @@ -117,7 +117,7 @@ func TestUnassignableField(t *testing.T) { } func TestNoParserForFlag(t *testing.T) { - var co ConfigOption + var co Option var invalidKey []time.Duration co.Name = "mykey" co.ConfigKey = &invalidKey @@ -256,7 +256,7 @@ func TestSetValue(t *testing.T) { }, } { t.Run(scenario.name, func(t *testing.T) { - co := ConfigOption{ + co := Option{ Name: scenario.name, ConfigKey: scenario.key, } diff --git a/cmd/soroban-rpc/internal/config/options.go b/cmd/soroban-rpc/internal/config/options.go index f417a7ee..e4838ab5 100644 --- a/cmd/soroban-rpc/internal/config/options.go +++ b/cmd/soroban-rpc/internal/config/options.go @@ -1,4 +1,4 @@ -//nolint:mnd // lots of magic constants due to default values +//nolint:mnd,lll // lots of magic constants and long lines due to default values and help strings package config import ( @@ -12,7 +12,6 @@ import ( "github.com/sirupsen/logrus" "github.com/stellar/go/network" - "github.com/stellar/go/support/errors" "github.com/stellar/go/support/strutils" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/ledgerbucketwindow" @@ -20,12 +19,15 @@ import ( const defaultHTTPEndpoint = "localhost:8000" -func (cfg *Config) options() ConfigOptions { +// TODO: refactor and remove the linter exceptions +// +//nolint:funlen,cyclop,maintidx +func (cfg *Config) options() Options { if cfg.optionsCache != nil { return *cfg.optionsCache } defaultStellarCoreBinaryPath, _ := exec.LookPath("stellar-core") - cfg.optionsCache = &ConfigOptions{ + cfg.optionsCache = &Options{ { Name: "config-path", EnvVar: "SOROBAN_RPC_CONFIG_PATH", @@ -56,7 +58,7 @@ func (cfg *Config) options() ConfigOptions { Name: "stellar-core-url", Usage: "URL used to query Stellar Core (local captive core by default)", ConfigKey: &cfg.StellarCoreURL, - Validate: func(co *ConfigOption) error { + Validate: func(_ *Option) error { // This is a bit awkward. We're actually setting a default, but we // can't do that until the config is fully parsed, so we do it as a // validator here. @@ -83,7 +85,7 @@ func (cfg *Config) options() ConfigOptions { Usage: "minimum log severity (debug, info, warn, error) to log", ConfigKey: &cfg.LogLevel, DefaultValue: logrus.InfoLevel, - CustomSetValue: func(option *ConfigOption, i interface{}) error { + CustomSetValue: func(option *Option, i interface{}) error { switch v := i.(type) { case nil: return nil @@ -102,7 +104,7 @@ func (cfg *Config) options() ConfigOptions { } return nil }, - MarshalTOML: func(option *ConfigOption) (interface{}, error) { + MarshalTOML: func(_ *Option) (interface{}, error) { return cfg.LogLevel.String(), nil }, }, @@ -111,15 +113,15 @@ func (cfg *Config) options() ConfigOptions { Usage: "format used for output logs (json or text)", ConfigKey: &cfg.LogFormat, DefaultValue: LogFormatText, - CustomSetValue: func(option *ConfigOption, i interface{}) error { + CustomSetValue: func(option *Option, i interface{}) error { switch v := i.(type) { case nil: return nil case string: - return errors.Wrapf( - cfg.LogFormat.UnmarshalText([]byte(v)), - "could not parse %s", + return fmt.Errorf( + "could not parse %s: %w", option.Name, + cfg.LogFormat.UnmarshalText([]byte(v)), ) case LogFormat: cfg.LogFormat = v @@ -130,7 +132,7 @@ func (cfg *Config) options() ConfigOptions { } return nil }, - MarshalTOML: func(option *ConfigOption) (interface{}, error) { + MarshalTOML: func(_ *Option) (interface{}, error) { return cfg.LogFormat.String() }, }, @@ -151,7 +153,7 @@ func (cfg *Config) options() ConfigOptions { Name: "captive-core-storage-path", Usage: "Storage location for Captive Core bucket data", ConfigKey: &cfg.CaptiveCoreStoragePath, - CustomSetValue: func(option *ConfigOption, i interface{}) error { + CustomSetValue: func(option *Option, i interface{}) error { switch v := i.(type) { case string: if v == "" || v == "." { @@ -255,7 +257,7 @@ func (cfg *Config) options() ConfigOptions { Usage: "Default cap on the amount of events included in a single getEvents response", ConfigKey: &cfg.DefaultEventsLimit, DefaultValue: uint(100), - Validate: func(co *ConfigOption) error { + Validate: func(_ *Option) error { if cfg.DefaultEventsLimit > cfg.MaxEventsLimit { return fmt.Errorf( "default-events-limit (%v) cannot exceed max-events-limit (%v)", @@ -277,7 +279,7 @@ func (cfg *Config) options() ConfigOptions { Usage: "Default cap on the amount of transactions included in a single getTransactions response", ConfigKey: &cfg.DefaultTransactionsLimit, DefaultValue: uint(50), - Validate: func(co *ConfigOption) error { + Validate: func(_ *Option) error { if cfg.DefaultTransactionsLimit > cfg.MaxTransactionsLimit { return fmt.Errorf( "default-transactions-limit (%v) cannot exceed max-transactions-limit (%v)", @@ -481,16 +483,16 @@ func (cfg *Config) options() ConfigOptions { return *cfg.optionsCache } -type errMissingRequiredOption struct { +type missingRequiredOptionError struct { strErr string usage string } -func (e errMissingRequiredOption) Error() string { +func (e missingRequiredOptionError) Error() string { return e.strErr } -func required(option *ConfigOption) error { +func required(option *Option) error { switch reflect.ValueOf(option.ConfigKey).Elem().Kind() { case reflect.Slice: if reflect.ValueOf(option.ConfigKey).Elem().Len() > 0 { @@ -524,10 +526,10 @@ func required(option *ConfigOption) error { advice = fmt.Sprintf(" Please %s, %s, or %s.", waysToSet[0], waysToSet[1], waysToSet[2]) } - return errMissingRequiredOption{strErr: fmt.Sprintf("%s is required.%s", option.Name, advice), usage: option.Usage} + return missingRequiredOptionError{strErr: fmt.Sprintf("%s is required.%s", option.Name, advice), usage: option.Usage} } -func positive(option *ConfigOption) error { +func positive(option *Option) error { switch v := option.ConfigKey.(type) { case *int, *int8, *int16, *int32, *int64: if reflect.ValueOf(v).Elem().Int() <= 0 { diff --git a/cmd/soroban-rpc/internal/config/options_test.go b/cmd/soroban-rpc/internal/config/options_test.go index 00b1654f..0478b628 100644 --- a/cmd/soroban-rpc/internal/config/options_test.go +++ b/cmd/soroban-rpc/internal/config/options_test.go @@ -15,7 +15,7 @@ func TestAllConfigKeysMustBePointers(t *testing.T) { for _, option := range cfg.options() { kind := reflect.ValueOf(option.ConfigKey).Type().Kind() if kind != reflect.Pointer { - t.Errorf("ConfigOption.ConfigKey must be a pointer, got %s for %s", kind, option.Name) + t.Errorf("Option.ConfigKey must be a pointer, got %s for %s", kind, option.Name) } } } @@ -33,7 +33,7 @@ func TestAllConfigFieldsMustHaveASingleOption(t *testing.T) { cfgType := cfgValue.Type() options := cfg.options() - optionsByField := map[uintptr]*ConfigOption{} + optionsByField := map[uintptr]*Option{} for _, option := range options { key := uintptr(reflect.ValueOf(option.ConfigKey).UnsafePointer()) if existing, ok := optionsByField[key]; ok { @@ -58,7 +58,7 @@ func TestAllConfigFieldsMustHaveASingleOption(t *testing.T) { // There should be an option which points to this field _, ok := optionsByField[fieldPointer] if !ok { - t.Errorf("Missing ConfigOption for field Config.%s", structField.Name) + t.Errorf("Missing Option for field Config.%s", structField.Name) } } } @@ -79,7 +79,7 @@ func TestAllOptionsMustHaveAUniqueValidTomlKey(t *testing.T) { // Allow us to explicitly exclude any fields on the Config struct, which are // not going to be in the toml. This should be the "Name" field of the - // ConfigOption we wish to exclude. + // Option we wish to exclude. excluded := map[string]bool{ "config-path": true, } @@ -91,12 +91,12 @@ func TestAllOptionsMustHaveAUniqueValidTomlKey(t *testing.T) { key, ok := option.getTomlKey() if excluded[option.Name] { if ok { - t.Errorf("Found unexpected toml key for excluded ConfigOption %s. Does the test need updating?", option.Name) + t.Errorf("Found unexpected toml key for excluded Option %s. Does the test need updating?", option.Name) } continue } if !ok { - t.Errorf("Missing toml key for ConfigOption %s", option.Name) + t.Errorf("Missing toml key for Option %s", option.Name) } if existing, ok := optionsByTomlKey[key]; ok { t.Errorf("Conflicting ConfigOptions %s and %s, have the same toml key: %s", existing, option.Name, key) @@ -104,6 +104,6 @@ func TestAllOptionsMustHaveAUniqueValidTomlKey(t *testing.T) { optionsByTomlKey[key] = option.Name // Ensure the keys are simple valid toml keys - assert.True(t, keyRegex.MatchString(key), "Invalid toml key for ConfigOption %s: %s", option.Name, key) + assert.True(t, keyRegex.MatchString(key), "Invalid toml key for Option %s: %s", option.Name, key) } } diff --git a/cmd/soroban-rpc/internal/config/parse.go b/cmd/soroban-rpc/internal/config/parse.go index 6001f5d7..58a5d80b 100644 --- a/cmd/soroban-rpc/internal/config/parse.go +++ b/cmd/soroban-rpc/internal/config/parse.go @@ -7,11 +7,9 @@ import ( "strconv" "strings" "time" - - "github.com/stellar/go/support/errors" ) -func parseBool(option *ConfigOption, i interface{}) error { +func parseBool(option *Option, i interface{}) error { switch v := i.(type) { case nil: return nil @@ -32,7 +30,7 @@ func parseBool(option *ConfigOption, i interface{}) error { return nil } -func parseInt(option *ConfigOption, i interface{}) error { +func parseInt(option *Option, i interface{}) error { switch v := i.(type) { case nil: return nil @@ -50,7 +48,7 @@ func parseInt(option *ConfigOption, i interface{}) error { return nil } -func parseUint(option *ConfigOption, i interface{}) error { +func parseUint(option *Option, i interface{}) error { switch v := i.(type) { case nil: return nil @@ -73,7 +71,7 @@ func parseUint(option *ConfigOption, i interface{}) error { return nil } -func parseFloat(option *ConfigOption, i interface{}) error { +func parseFloat(option *Option, i interface{}) error { switch v := i.(type) { case nil: return nil @@ -91,7 +89,7 @@ func parseFloat(option *ConfigOption, i interface{}) error { return nil } -func parseString(option *ConfigOption, i interface{}) error { +func parseString(option *Option, i interface{}) error { switch v := i.(type) { case nil: return nil @@ -103,7 +101,7 @@ func parseString(option *ConfigOption, i interface{}) error { return nil } -func parseUint32(option *ConfigOption, i interface{}) error { +func parseUint32(option *Option, i interface{}) error { switch v := i.(type) { case nil: return nil @@ -129,14 +127,14 @@ func parseUint32(option *ConfigOption, i interface{}) error { return nil } -func parseDuration(option *ConfigOption, i interface{}) error { +func parseDuration(option *Option, i interface{}) error { switch v := i.(type) { case nil: return nil case string: d, err := time.ParseDuration(v) if err != nil { - return errors.Wrapf(err, "could not parse duration: %q", v) + return fmt.Errorf("could not parse duration: %q: %w", v, err) } *option.ConfigKey.(*time.Duration) = d case time.Duration: @@ -149,7 +147,7 @@ func parseDuration(option *ConfigOption, i interface{}) error { return nil } -func parseStringSlice(option *ConfigOption, i interface{}) error { +func parseStringSlice(option *Option, i interface{}) error { switch v := i.(type) { case nil: return nil diff --git a/cmd/soroban-rpc/internal/config/toml_test.go b/cmd/soroban-rpc/internal/config/toml_test.go index 93fa1809..0b438996 100644 --- a/cmd/soroban-rpc/internal/config/toml_test.go +++ b/cmd/soroban-rpc/internal/config/toml_test.go @@ -8,9 +8,10 @@ import ( "time" "github.com/sirupsen/logrus" - "github.com/stellar/go/network" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/stellar/go/network" ) const basicToml = ` diff --git a/cmd/soroban-rpc/internal/config/version.go b/cmd/soroban-rpc/internal/config/version.go index 909fdaea..3e203dde 100644 --- a/cmd/soroban-rpc/internal/config/version.go +++ b/cmd/soroban-rpc/internal/config/version.go @@ -1,3 +1,4 @@ +//nolint:gochecknoglobals // allow global variables package config var ( diff --git a/cmd/soroban-rpc/internal/daemon/daemon.go b/cmd/soroban-rpc/internal/daemon/daemon.go index bf55fa4a..5ca3004b 100644 --- a/cmd/soroban-rpc/internal/daemon/daemon.go +++ b/cmd/soroban-rpc/internal/daemon/daemon.go @@ -51,7 +51,7 @@ type Daemon struct { db *db.DB jsonRPCHandler *internal.Handler logger *supportlog.Entry - preflightWorkerPool *preflight.PreflightWorkerPool + preflightWorkerPool *preflight.WorkerPool listener net.Listener server *http.Server adminListener net.Listener @@ -238,13 +238,15 @@ func MustNew(cfg *config.Config, logger *supportlog.Entry) *Daemon { ledgerEntryReader := db.NewLedgerEntryReader(dbConn) preflightWorkerPool := preflight.NewPreflightWorkerPool( - daemon, - cfg.PreflightWorkerCount, - cfg.PreflightWorkerQueueSize, - cfg.PreflightEnableDebug, - ledgerEntryReader, - cfg.NetworkPassphrase, - logger, + preflight.WorkerPoolConfig{ + Daemon: daemon, + WorkerCount: cfg.PreflightWorkerCount, + JobQueueCapacity: cfg.PreflightWorkerQueueSize, + EnableDebug: cfg.PreflightEnableDebug, + LedgerEntryReader: ledgerEntryReader, + NetworkPassphrase: cfg.NetworkPassphrase, + Logger: logger, + }, ) jsonRPCHandler := internal.NewJSONRPCHandler(cfg, internal.HandlerParams{ diff --git a/cmd/soroban-rpc/internal/daemon/interfaces/noOpDaemon.go b/cmd/soroban-rpc/internal/daemon/interfaces/noOpDaemon.go index 79a63971..db8d513d 100644 --- a/cmd/soroban-rpc/internal/daemon/interfaces/noOpDaemon.go +++ b/cmd/soroban-rpc/internal/daemon/interfaces/noOpDaemon.go @@ -10,29 +10,29 @@ import ( // The noOpDeamon is a dummy daemon implementation, supporting the Daemon interface. // Used only in testing. -type noOpDaemon struct { +type NoOpDaemon struct { metricsRegistry *prometheus.Registry metricsNamespace string coreClient noOpCoreClient } -func MakeNoOpDeamon() *noOpDaemon { - return &noOpDaemon{ +func MakeNoOpDeamon() *NoOpDaemon { + return &NoOpDaemon{ metricsRegistry: prometheus.NewRegistry(), metricsNamespace: "soroban_rpc", coreClient: noOpCoreClient{}, } } -func (d *noOpDaemon) MetricsRegistry() *prometheus.Registry { +func (d *NoOpDaemon) MetricsRegistry() *prometheus.Registry { return prometheus.NewRegistry() // so that you can register metrics many times } -func (d *noOpDaemon) MetricsNamespace() string { +func (d *NoOpDaemon) MetricsNamespace() string { return d.metricsNamespace } -func (d *noOpDaemon) CoreClient() CoreClient { +func (d *NoOpDaemon) CoreClient() CoreClient { return d.coreClient } diff --git a/cmd/soroban-rpc/internal/db/db.go b/cmd/soroban-rpc/internal/db/db.go index 966f8cd8..1767f610 100644 --- a/cmd/soroban-rpc/internal/db/db.go +++ b/cmd/soroban-rpc/internal/db/db.go @@ -4,6 +4,7 @@ import ( "context" "database/sql" "embed" + "errors" "fmt" "strconv" "sync" @@ -14,7 +15,6 @@ import ( migrate "github.com/rubenv/sql-migrate" "github.com/stellar/go/support/db" - "github.com/stellar/go/support/errors" "github.com/stellar/go/support/log" "github.com/stellar/go/xdr" @@ -63,12 +63,12 @@ func openSQLiteDB(dbFilePath string) (*db.Session, error) { // 3. Use synchronous=NORMAL, which is faster and still safe in WAL mode. session, err := db.Open("sqlite3", fmt.Sprintf("file:%s?_journal_mode=WAL&_wal_autocheckpoint=0&_synchronous=NORMAL", dbFilePath)) if err != nil { - return nil, errors.Wrap(err, "open failed") + return nil, fmt.Errorf("open failed: %w", err) } if err = runSQLMigrations(session.DB.DB, "sqlite3"); err != nil { _ = session.Close() - return nil, errors.Wrap(err, "could not run SQL migrations") + return nil, fmt.Errorf("could not run SQL migrations: %w", err) } return session, nil } diff --git a/cmd/soroban-rpc/internal/db/ledger_test.go b/cmd/soroban-rpc/internal/db/ledger_test.go index 25369fac..a40bc255 100644 --- a/cmd/soroban-rpc/internal/db/ledger_test.go +++ b/cmd/soroban-rpc/internal/db/ledger_test.go @@ -15,8 +15,10 @@ import ( "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/daemon/interfaces" ) -var passphrase = network.FutureNetworkPassphrase -var logger = log.DefaultLogger +var ( + passphrase = network.FutureNetworkPassphrase + logger = log.DefaultLogger +) func createLedger(ledgerSequence uint32) xdr.LedgerCloseMeta { return xdr.LedgerCloseMeta{ diff --git a/cmd/soroban-rpc/internal/db/ledgerentry.go b/cmd/soroban-rpc/internal/db/ledgerentry.go index 62677425..60e3a259 100644 --- a/cmd/soroban-rpc/internal/db/ledgerentry.go +++ b/cmd/soroban-rpc/internal/db/ledgerentry.go @@ -4,12 +4,12 @@ import ( "context" "crypto/sha256" "database/sql" + "errors" "fmt" sq "github.com/Masterminds/squirrel" "github.com/stellar/go/support/db" - "github.com/stellar/go/support/errors" "github.com/stellar/go/xdr" ) @@ -54,7 +54,7 @@ func (l ledgerEntryWriter) UpsertLedgerEntry(entry xdr.LedgerEntry) error { // because the key can be derived from the entry. key, err := entry.LedgerKey() if err != nil { - return errors.Wrap(err, "could not get ledger key from entry") + return fmt.Errorf("could not get ledger key from entry: %w", err) } encodedKey, err := encodeLedgerKey(l.buffer, key) @@ -304,7 +304,7 @@ func (l *ledgerEntryReadTx) GetLedgerEntries(keys ...xdr.LedgerKey) ([]LedgerKey } var entry xdr.LedgerEntry if err := xdr.SafeUnmarshal([]byte(encodedEntry), &entry); err != nil { - return nil, errors.Wrap(err, "cannot decode ledger entry from DB") + return nil, fmt.Errorf("cannot decode ledger entry from DB: %w", err) } if k2e.encodedTTLKey == nil { result = append(result, LedgerKeyAndEntry{k2e.key, entry, nil}) @@ -317,7 +317,7 @@ func (l *ledgerEntryReadTx) GetLedgerEntries(keys ...xdr.LedgerKey) ([]LedgerKey } var ttlEntry xdr.LedgerEntry if err := xdr.SafeUnmarshal([]byte(encodedTTLEntry), &ttlEntry); err != nil { - return nil, errors.Wrap(err, "cannot decode TTL ledger entry from DB") + return nil, fmt.Errorf("cannot decode TTL ledger entry from DB: %w", err) } liveUntilSeq := uint32(ttlEntry.Data.Ttl.LiveUntilLedgerSeq) result = append(result, LedgerKeyAndEntry{k2e.key, entry, &liveUntilSeq}) diff --git a/cmd/soroban-rpc/internal/db/ledgerentry_test.go b/cmd/soroban-rpc/internal/db/ledgerentry_test.go index 34b1b41e..08526709 100644 --- a/cmd/soroban-rpc/internal/db/ledgerentry_test.go +++ b/cmd/soroban-rpc/internal/db/ledgerentry_test.go @@ -13,6 +13,7 @@ import ( "github.com/stellar/go/support/log" "github.com/stellar/go/xdr" + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/daemon/interfaces" ) @@ -483,7 +484,6 @@ forloop: t.Log(msg) } } - } func benchmarkLedgerEntry(b *testing.B, cached bool) { diff --git a/cmd/soroban-rpc/internal/db/migration.go b/cmd/soroban-rpc/internal/db/migration.go index 8ca9d702..74a88f87 100644 --- a/cmd/soroban-rpc/internal/db/migration.go +++ b/cmd/soroban-rpc/internal/db/migration.go @@ -172,7 +172,6 @@ func (g *guardedMigration) Commit(ctx context.Context) error { } err := setMetaBool(ctx, g.db, g.guardMetaKey, true) if err != nil { - g.Rollback(ctx) return errors.Join(err, g.Rollback(ctx)) } return g.db.Commit() diff --git a/cmd/soroban-rpc/internal/db/transaction.go b/cmd/soroban-rpc/internal/db/transaction.go index 43856945..fdb8b5b9 100644 --- a/cmd/soroban-rpc/internal/db/transaction.go +++ b/cmd/soroban-rpc/internal/db/transaction.go @@ -3,6 +3,7 @@ package db import ( "context" "encoding/hex" + "errors" "fmt" "time" @@ -11,7 +12,6 @@ import ( "github.com/stellar/go/ingest" "github.com/stellar/go/support/db" - "github.com/stellar/go/support/errors" "github.com/stellar/go/support/log" "github.com/stellar/go/xdr" @@ -80,16 +80,18 @@ func (txn *transactionHandler) InsertTransactions(lcm xdr.LedgerCloseMeta) error reader, err := ingest.NewLedgerTransactionReaderFromLedgerCloseMeta(txn.passphrase, lcm) if err != nil { - return errors.Wrapf(err, - "failed to open transaction reader for ledger %d", - lcm.LedgerSequence()) + return fmt.Errorf( + "failed to open transaction reader for ledger %d: %w", + lcm.LedgerSequence(), + err, + ) } transactions := make(map[xdr.Hash]ingest.LedgerTransaction, txCount) for i := 0; i < txCount; i++ { tx, err := reader.Read() if err != nil { - return errors.Wrapf(err, "failed reading tx %d", i) + return fmt.Errorf("failed reading tx %d: %w", i, err) } // For fee-bump transactions, we store lookup entries for both the outer @@ -163,12 +165,12 @@ func (txn *transactionHandler) GetLedgerRange(ctx context.Context) (ledgerbucket "m2", ).ToSql() if err != nil { - return ledgerRange, errors.Wrap(err, "couldn't build ledger range query") + return ledgerRange, fmt.Errorf("couldn't build ledger range query: %w", err) } var lcms []xdr.LedgerCloseMeta if err = txn.db.Select(ctx, &lcms, newestQ.Suffix("UNION ALL "+sql, args...)); err != nil { - return ledgerRange, errors.Wrap(err, "couldn't query ledger range") + return ledgerRange, fmt.Errorf("couldn't query ledger range: %w", err) } else if len(lcms) < 2 { // There is almost certainly a row, but we want to avoid a race condition // with ingestion as well as support test cases from an empty DB, so we need @@ -244,18 +246,22 @@ func (txn *transactionHandler) getTransactionByHash(ctx context.Context, hash xd if err := txn.db.Select(ctx, &rows, rowQ); err != nil { return xdr.LedgerCloseMeta{}, ingest.LedgerTransaction{}, - errors.Wrapf(err, "db read failed for txhash %s", hex.EncodeToString(hash[:])) + fmt.Errorf("db read failed for txhash %s: %w", hex.EncodeToString(hash[:]), err) } else if len(rows) < 1 { return xdr.LedgerCloseMeta{}, ingest.LedgerTransaction{}, ErrNoTransaction } txIndex, lcm := rows[0].TxIndex, rows[0].Lcm reader, err := ingest.NewLedgerTransactionReaderFromLedgerCloseMeta(txn.passphrase, lcm) - reader.Seek(txIndex - 1) if err != nil { return lcm, ingest.LedgerTransaction{}, - errors.Wrapf(err, "failed to index to tx %d in ledger %d (txhash=%s)", - txIndex, lcm.LedgerSequence(), hash) + fmt.Errorf("failed to create ledger reader: %w", err) + } + err = reader.Seek(txIndex - 1) + if err != nil { + return lcm, ingest.LedgerTransaction{}, + fmt.Errorf("failed to index to tx %d in ledger %d (txhash=%s): %w", + txIndex, lcm.LedgerSequence(), hash, err) } ledgerTx, err := reader.Read() @@ -278,25 +284,25 @@ func ParseTransaction(lcm xdr.LedgerCloseMeta, ingestTx ingest.LedgerTransaction } if tx.Result, err = ingestTx.Result.Result.MarshalBinary(); err != nil { - return tx, errors.Wrap(err, "couldn't encode transaction Result") + return tx, fmt.Errorf("couldn't encode transaction Result: %w", err) } if tx.Meta, err = ingestTx.UnsafeMeta.MarshalBinary(); err != nil { - return tx, errors.Wrap(err, "couldn't encode transaction UnsafeMeta") + return tx, fmt.Errorf("couldn't encode transaction UnsafeMeta: %w", err) } if tx.Envelope, err = ingestTx.Envelope.MarshalBinary(); err != nil { - return tx, errors.Wrap(err, "couldn't encode transaction Envelope") + return tx, fmt.Errorf("couldn't encode transaction Envelope: %w", err) } if events, diagErr := ingestTx.GetDiagnosticEvents(); diagErr == nil { tx.Events = make([][]byte, 0, len(events)) for i, event := range events { bytes, ierr := event.MarshalBinary() if ierr != nil { - return tx, errors.Wrapf(ierr, "couldn't encode transaction DiagnosticEvent %d", i) + return tx, fmt.Errorf("couldn't encode transaction DiagnosticEvent %d: %w", i, ierr) } tx.Events = append(tx.Events, bytes) } } else { - return tx, errors.Wrap(diagErr, "couldn't encode transaction DiagnosticEvents") + return tx, fmt.Errorf("couldn't encode transaction DiagnosticEvents: %w", diagErr) } return tx, nil diff --git a/cmd/soroban-rpc/internal/db/transaction_test.go b/cmd/soroban-rpc/internal/db/transaction_test.go index 7257c1e1..a4bf2342 100644 --- a/cmd/soroban-rpc/internal/db/transaction_test.go +++ b/cmd/soroban-rpc/internal/db/transaction_test.go @@ -7,14 +7,14 @@ import ( "testing" "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stellar/go/network" "github.com/stellar/go/support/log" "github.com/stellar/go/xdr" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/daemon/interfaces" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestTransactionNotFound(t *testing.T) { diff --git a/cmd/soroban-rpc/internal/events/cursor.go b/cmd/soroban-rpc/internal/events/cursor.go index 3fbfbecb..8be24efa 100644 --- a/cmd/soroban-rpc/internal/events/cursor.go +++ b/cmd/soroban-rpc/internal/events/cursor.go @@ -48,11 +48,11 @@ func (c *Cursor) UnmarshalJSON(b []byte) error { return err } - if parsed, err := ParseCursor(s); err != nil { + parsed, err := ParseCursor(s) + if err != nil { return err - } else { - *c = parsed } + *c = parsed return nil } @@ -113,8 +113,10 @@ func (c Cursor) Cmp(other Cursor) int { var ( // MinCursor is the smallest possible cursor + //nolint:gochecknoglobals MinCursor = Cursor{} // MaxCursor is the largest possible cursor + //nolint:gochecknoglobals MaxCursor = Cursor{ Ledger: math.MaxUint32, Tx: math.MaxUint32, diff --git a/cmd/soroban-rpc/internal/events/events_test.go b/cmd/soroban-rpc/internal/events/events_test.go index c5fda34c..50012fe9 100644 --- a/cmd/soroban-rpc/internal/events/events_test.go +++ b/cmd/soroban-rpc/internal/events/events_test.go @@ -6,9 +6,10 @@ import ( "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" - "github.com/stellar/go/xdr" "github.com/stretchr/testify/require" + "github.com/stellar/go/xdr" + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/daemon/interfaces" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/ledgerbucketwindow" ) diff --git a/cmd/soroban-rpc/internal/feewindow/feewindow.go b/cmd/soroban-rpc/internal/feewindow/feewindow.go index a65210e3..3d662fbc 100644 --- a/cmd/soroban-rpc/internal/feewindow/feewindow.go +++ b/cmd/soroban-rpc/internal/feewindow/feewindow.go @@ -53,7 +53,7 @@ func (fw *FeeWindow) AppendLedgerFees(fees ledgerbucketwindow.LedgerBucket[[]uin } var allFees []uint64 - for i := uint32(0); i < fw.feesPerLedger.Len(); i++ { + for i := range fw.feesPerLedger.Len() { allFees = append(allFees, fw.feesPerLedger.Get(i).BucketContent...) } fw.distribution = computeFeeDistribution(allFees, fw.feesPerLedger.Len()) @@ -72,7 +72,7 @@ func computeFeeDistribution(fees []uint64, ledgerCount uint32) FeeDistribution { localRepetitions := 0 for i := 1; i < len(fees); i++ { if fees[i] == lastVal { - localRepetitions += 1 + localRepetitions++ continue } @@ -166,7 +166,8 @@ func (fw *FeeWindows) IngestFees(meta xdr.LedgerCloseMeta) error { continue } sorobanFees := tx.UnsafeMeta.V3.SorobanMeta.Ext.V1 - resourceFeeCharged := sorobanFees.TotalNonRefundableResourceFeeCharged + sorobanFees.TotalRefundableResourceFeeCharged + resourceFeeCharged := sorobanFees.TotalNonRefundableResourceFeeCharged + + sorobanFees.TotalRefundableResourceFeeCharged inclusionFee := feeCharged - uint64(resourceFeeCharged) sorobanInclusionFees = append(sorobanInclusionFees, inclusionFee) continue diff --git a/cmd/soroban-rpc/internal/feewindow/feewindow_test.go b/cmd/soroban-rpc/internal/feewindow/feewindow_test.go index 53969ff2..cd28bcad 100644 --- a/cmd/soroban-rpc/internal/feewindow/feewindow_test.go +++ b/cmd/soroban-rpc/internal/feewindow/feewindow_test.go @@ -19,7 +19,8 @@ func TestBasicComputeFeeDistribution(t *testing.T) { }{ {"nil", nil, FeeDistribution{}}, {"empty", []uint64{}, FeeDistribution{}}, - {"one", + { + "one", []uint64{100}, FeeDistribution{ Max: 100, @@ -39,7 +40,8 @@ func TestBasicComputeFeeDistribution(t *testing.T) { FeeCount: 1, }, }, - {"even number of elements: four 100s and six 1000s", + { + "even number of elements: four 100s and six 1000s", []uint64{100, 100, 100, 1000, 100, 1000, 1000, 1000, 1000, 1000}, FeeDistribution{ Max: 1000, @@ -59,7 +61,8 @@ func TestBasicComputeFeeDistribution(t *testing.T) { FeeCount: 10, }, }, - {"odd number of elements: five 100s and six 1000s", + { + "odd number of elements: five 100s and six 1000s", []uint64{100, 100, 100, 1000, 100, 1000, 1000, 1000, 1000, 1000, 100}, FeeDistribution{ Max: 1000, @@ -79,7 +82,8 @@ func TestBasicComputeFeeDistribution(t *testing.T) { FeeCount: 11, }, }, - {"mutiple modes favors the smallest value", + { + "mutiple modes favors the smallest value", []uint64{100, 1000}, FeeDistribution{ Max: 1000, @@ -99,7 +103,8 @@ func TestBasicComputeFeeDistribution(t *testing.T) { FeeCount: 2, }, }, - {"random distribution with a repetition", + { + "random distribution with a repetition", []uint64{515, 245, 245, 530, 221, 262, 927}, FeeDistribution{ Max: 927, @@ -119,7 +124,8 @@ func TestBasicComputeFeeDistribution(t *testing.T) { FeeCount: 7, }, }, - {"random distribution with a repetition of its largest value", + { + "random distribution with a repetition of its largest value", []uint64{515, 245, 530, 221, 262, 927, 927}, FeeDistribution{ Max: 927, @@ -145,7 +151,6 @@ func TestBasicComputeFeeDistribution(t *testing.T) { } func TestComputeFeeDistributionAgainstAlternative(t *testing.T) { - for i := 0; i < 100_000; i++ { fees := generateFees(nil) feesCopy1 := make([]uint64, len(fees)) diff --git a/cmd/soroban-rpc/internal/ingest/service_test.go b/cmd/soroban-rpc/internal/ingest/service_test.go index 32b55327..dbeeb1f6 100644 --- a/cmd/soroban-rpc/internal/ingest/service_test.go +++ b/cmd/soroban-rpc/internal/ingest/service_test.go @@ -21,18 +21,17 @@ import ( "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/feewindow" ) -type ErrorReadWriter struct { -} +type ErrorReadWriter struct{} func (rw *ErrorReadWriter) GetLatestLedgerSequence(ctx context.Context) (uint32, error) { return 0, errors.New("could not get latest ledger sequence") } + func (rw *ErrorReadWriter) NewTx(ctx context.Context) (db.WriteTx, error) { return nil, errors.New("could not create new tx") } func TestRetryRunningIngestion(t *testing.T) { - var retryWg sync.WaitGroup retryWg.Add(1) diff --git a/cmd/soroban-rpc/internal/integrationtest/get_fee_stats_test.go b/cmd/soroban-rpc/internal/integrationtest/get_fee_stats_test.go index 407ebb13..7ec8e132 100644 --- a/cmd/soroban-rpc/internal/integrationtest/get_fee_stats_test.go +++ b/cmd/soroban-rpc/internal/integrationtest/get_fee_stats_test.go @@ -4,11 +4,12 @@ import ( "context" "testing" - "github.com/stellar/go/txnbuild" - "github.com/stellar/go/xdr" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/stellar/go/txnbuild" + "github.com/stellar/go/xdr" + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/integrationtest/infrastructure" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/methods" ) diff --git a/cmd/soroban-rpc/internal/integrationtest/get_transactions_test.go b/cmd/soroban-rpc/internal/integrationtest/get_transactions_test.go index 6af5954f..6c66efb0 100644 --- a/cmd/soroban-rpc/internal/integrationtest/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/integrationtest/get_transactions_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/assert" + "github.com/stellar/go/keypair" "github.com/stellar/go/txnbuild" - "github.com/stretchr/testify/assert" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/integrationtest/infrastructure" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/methods" @@ -62,7 +63,7 @@ func TestGetTransactions(t *testing.T) { } err := client.CallResult(context.Background(), "getTransactions", request, &result) assert.NoError(t, err) - assert.Equal(t, len(result.Transactions), 3) + assert.Len(t, result.Transactions, 3) assert.Equal(t, result.Transactions[0].Ledger, ledgers[0]) assert.Equal(t, result.Transactions[1].Ledger, ledgers[1]) assert.Equal(t, result.Transactions[2].Ledger, ledgers[2]) @@ -76,7 +77,7 @@ func TestGetTransactions(t *testing.T) { } err = client.CallResult(context.Background(), "getTransactions", request, &result) assert.NoError(t, err) - assert.Equal(t, len(result.Transactions), 1) + assert.Len(t, result.Transactions, 1) assert.Equal(t, result.Transactions[0].Ledger, ledgers[0]) // Get transactions using previous result's cursor @@ -88,7 +89,7 @@ func TestGetTransactions(t *testing.T) { } err = client.CallResult(context.Background(), "getTransactions", request, &result) assert.NoError(t, err) - assert.Equal(t, len(result.Transactions), 2) + assert.Len(t, result.Transactions, 2) assert.Equal(t, result.Transactions[0].Ledger, ledgers[1]) assert.Equal(t, result.Transactions[1].Ledger, ledgers[2]) } diff --git a/cmd/soroban-rpc/internal/integrationtest/get_version_info_test.go b/cmd/soroban-rpc/internal/integrationtest/get_version_info_test.go index b1bdb858..363f0115 100644 --- a/cmd/soroban-rpc/internal/integrationtest/get_version_info_test.go +++ b/cmd/soroban-rpc/internal/integrationtest/get_version_info_test.go @@ -4,11 +4,10 @@ import ( "context" "testing" - "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/config" - "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/integrationtest/infrastructure" - "github.com/stretchr/testify/assert" + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/config" + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/integrationtest/infrastructure" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/methods" ) diff --git a/cmd/soroban-rpc/internal/integrationtest/infrastructure/client.go b/cmd/soroban-rpc/internal/integrationtest/infrastructure/client.go index 4dfdedc0..18a154cb 100644 --- a/cmd/soroban-rpc/internal/integrationtest/infrastructure/client.go +++ b/cmd/soroban-rpc/internal/integrationtest/infrastructure/client.go @@ -7,12 +7,13 @@ import ( "github.com/creachadair/jrpc2" "github.com/creachadair/jrpc2/jhttp" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stellar/go/keypair" "github.com/stellar/go/protocols/stellarcore" "github.com/stellar/go/txnbuild" "github.com/stellar/go/xdr" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/methods" ) @@ -161,7 +162,7 @@ func PreflightTransactionParamsLocally(t *testing.T, params txnbuild.Transaction for _, b64 := range response.Results[0].Auth { var a xdr.SorobanAuthorizationEntry err := xdr.SafeUnmarshalBase64(b64, &a) - assert.NoError(t, err) + require.NoError(t, err) auth = append(auth, a) } v.Auth = auth diff --git a/cmd/soroban-rpc/internal/integrationtest/infrastructure/contract.go b/cmd/soroban-rpc/internal/integrationtest/infrastructure/contract.go index 4daa1427..9afd5ae1 100644 --- a/cmd/soroban-rpc/internal/integrationtest/infrastructure/contract.go +++ b/cmd/soroban-rpc/internal/integrationtest/infrastructure/contract.go @@ -7,9 +7,10 @@ import ( "path" "testing" + "github.com/stretchr/testify/require" + "github.com/stellar/go/txnbuild" "github.com/stellar/go/xdr" - "github.com/stretchr/testify/require" ) var testSalt = sha256.Sum256([]byte("a1")) diff --git a/cmd/soroban-rpc/internal/integrationtest/infrastructure/test.go b/cmd/soroban-rpc/internal/integrationtest/infrastructure/test.go index 9279ae77..f8996e12 100644 --- a/cmd/soroban-rpc/internal/integrationtest/infrastructure/test.go +++ b/cmd/soroban-rpc/internal/integrationtest/infrastructure/test.go @@ -210,7 +210,6 @@ func (i *Test) stopContainers() { } downCmd = append(downCmd, "-v") i.runSuccessfulComposeCommand(downCmd...) - } func (i *Test) GetPorts() TestPorts { @@ -224,6 +223,7 @@ func (i *Test) runRPCInContainer() bool { func (i *Test) GetRPCLient() *Client { return i.rpcClient } + func (i *Test) MasterKey() *keypair.Full { return keypair.Root(StandaloneNetworkPassphrase) } @@ -378,7 +378,8 @@ func (i *Test) generateCaptiveCoreCfg(tmplContents []byte, captiveCorePort uint1 } captiveCoreCfgContents := os.Expand(string(tmplContents), mapping) - err := os.WriteFile(filepath.Join(i.rpcConfigFilesDir, captiveCoreConfigFilename), []byte(captiveCoreCfgContents), 0666) + fileName := filepath.Join(i.rpcConfigFilesDir, captiveCoreConfigFilename) + err := os.WriteFile(fileName, []byte(captiveCoreCfgContents), 0o666) require.NoError(i.t, err) } @@ -393,7 +394,7 @@ func (i *Test) generateRPCConfigFile(rpcConfig rpcConfig) { for k, v := range rpcConfig.toMap() { cfgFileContents += fmt.Sprintf("%s=%q\n", k, v) } - err := os.WriteFile(filepath.Join(i.rpcConfigFilesDir, "soroban-rpc.config"), []byte(cfgFileContents), 0666) + err := os.WriteFile(filepath.Join(i.rpcConfigFilesDir, "soroban-rpc.config"), []byte(cfgFileContents), 0o666) require.NoError(i.t, err) } @@ -442,7 +443,7 @@ func (i *Test) createRPCDaemon(c rpcConfig) *daemon.Daemon { } require.NoError(i.t, cfg.SetValues(lookup)) require.NoError(i.t, cfg.Validate()) - cfg.HistoryArchiveUserAgent = fmt.Sprintf("soroban-rpc/%s", config.Version) + cfg.HistoryArchiveUserAgent = "soroban-rpc/" + config.Version logger := supportlog.New() logger.SetOutput(newTestLogWriter(i.t, `rpc="daemon" `)) diff --git a/cmd/soroban-rpc/internal/integrationtest/infrastructure/util.go b/cmd/soroban-rpc/internal/integrationtest/infrastructure/util.go index 3cd791b3..1a34325a 100644 --- a/cmd/soroban-rpc/internal/integrationtest/infrastructure/util.go +++ b/cmd/soroban-rpc/internal/integrationtest/infrastructure/util.go @@ -1,14 +1,13 @@ package infrastructure import ( - "fmt" "net" "path/filepath" "runtime" - "time" - "github.com/stellar/go/txnbuild" "github.com/stretchr/testify/require" + + "github.com/stellar/go/txnbuild" ) //go:noinline @@ -39,14 +38,3 @@ func CreateTransactionParams(account txnbuild.Account, op txnbuild.Operation) tx }, } } - -func isLocalTCPPortOpen(port uint16) bool { - host := fmt.Sprintf("localhost:%d", port) - timeout := time.Second - conn, err := net.DialTimeout("tcp", host, timeout) - if err != nil { - return false - } - conn.Close() - return true -} diff --git a/cmd/soroban-rpc/internal/integrationtest/metrics_test.go b/cmd/soroban-rpc/internal/integrationtest/metrics_test.go index 6d0cf1ae..930a6ed8 100644 --- a/cmd/soroban-rpc/internal/integrationtest/metrics_test.go +++ b/cmd/soroban-rpc/internal/integrationtest/metrics_test.go @@ -9,11 +9,11 @@ import ( "testing" io_prometheus_client "github.com/prometheus/client_model/go" - "github.com/stellar/go/support/errors" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + "github.com/stellar/go/support/errors" + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/config" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/integrationtest/infrastructure" ) @@ -43,13 +43,13 @@ func TestMetrics(t *testing.T) { assert.NoError(t, err) var metric *io_prometheus_client.MetricFamily for _, mf := range metricFamilies { - if *mf.Name == "soroban_rpc_log_error_total" { + if mf.GetName() == "soroban_rpc_log_error_total" { metric = mf break } } assert.NotNil(t, metric) - val := metric.Metric[0].Counter.GetValue() + val := metric.GetMetric()[0].GetCounter().GetValue() assert.GreaterOrEqual(t, val, 2.0) } diff --git a/cmd/soroban-rpc/internal/integrationtest/migrate_test.go b/cmd/soroban-rpc/internal/integrationtest/migrate_test.go index dd3c9b9c..750b8b82 100644 --- a/cmd/soroban-rpc/internal/integrationtest/migrate_test.go +++ b/cmd/soroban-rpc/internal/integrationtest/migrate_test.go @@ -72,7 +72,7 @@ func testMigrateFromVersion(t *testing.T, version string) { } err := test.GetRPCLient().CallResult(context.Background(), "getTransactions", getTransactions, &transactionsResult) require.NoError(t, err) - require.Equal(t, 1, len(transactionsResult.Transactions)) + require.Len(t, transactionsResult.Transactions, 1) require.Equal(t, submitTransactionResponse.Ledger, transactionsResult.Transactions[0].Ledger) var eventsResult methods.GetEventsResponse @@ -84,7 +84,7 @@ func testMigrateFromVersion(t *testing.T, version string) { } err = test.GetRPCLient().CallResult(context.Background(), "getEvents", getEventsRequest, &eventsResult) require.NoError(t, err) - require.Equal(t, len(eventsResult.Events), 1) + require.Len(t, eventsResult.Events, 1) require.Equal(t, submitTransactionResponse.Ledger, uint32(eventsResult.Events[0].Ledger)) } diff --git a/cmd/soroban-rpc/internal/integrationtest/transaction_test.go b/cmd/soroban-rpc/internal/integrationtest/transaction_test.go index ddda9f68..37a0c9be 100644 --- a/cmd/soroban-rpc/internal/integrationtest/transaction_test.go +++ b/cmd/soroban-rpc/internal/integrationtest/transaction_test.go @@ -5,11 +5,12 @@ import ( "testing" "github.com/creachadair/jrpc2" + "github.com/stretchr/testify/assert" + "github.com/stellar/go/keypair" proto "github.com/stellar/go/protocols/stellarcore" "github.com/stellar/go/txnbuild" "github.com/stellar/go/xdr" - "github.com/stretchr/testify/assert" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/integrationtest/infrastructure" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/methods" @@ -130,11 +131,10 @@ func TestSendTransactionFailedInsufficientResourceFee(t *testing.T) { assert.NoError(t, xdr.SafeUnmarshalBase64(result.ErrorResultXDR, &errorResult)) assert.Equal(t, xdr.TransactionResultCodeTxSorobanInvalid, errorResult.Result.Code) - assert.Greater(t, len(result.DiagnosticEventsXDR), 0) + assert.NotEmpty(t, result.DiagnosticEventsXDR) var event xdr.DiagnosticEvent err = xdr.SafeUnmarshalBase64(result.DiagnosticEventsXDR[0], &event) assert.NoError(t, err) - } func TestSendTransactionFailedInLedger(t *testing.T) { diff --git a/cmd/soroban-rpc/internal/integrationtest/upgrade_test.go b/cmd/soroban-rpc/internal/integrationtest/upgrade_test.go index 386e95ff..efd26cb2 100644 --- a/cmd/soroban-rpc/internal/integrationtest/upgrade_test.go +++ b/cmd/soroban-rpc/internal/integrationtest/upgrade_test.go @@ -5,9 +5,10 @@ import ( "testing" "time" - "github.com/stellar/go/xdr" "github.com/stretchr/testify/require" + "github.com/stellar/go/xdr" + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/db" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/integrationtest/infrastructure" ) diff --git a/cmd/soroban-rpc/internal/jsonrpc.go b/cmd/soroban-rpc/internal/jsonrpc.go index 01d0efeb..aede6b93 100644 --- a/cmd/soroban-rpc/internal/jsonrpc.go +++ b/cmd/soroban-rpc/internal/jsonrpc.go @@ -307,7 +307,7 @@ func NewJSONRPCHandler(cfg *config.Config, params HandlerParams) Handler { Namespace: params.Daemon.MetricsNamespace(), Subsystem: "network", Name: "global_request_execution_duration_threshold_limit", Help: "The metric measures the count of requests that surpassed the limit threshold for execution time", }) - var handler http.Handler = network.MakeHTTPRequestDurationLimiter( + handler := network.MakeHTTPRequestDurationLimiter( queueLimitedBridge, cfg.RequestExecutionWarningThreshold, cfg.MaxRequestExecutionDuration, diff --git a/cmd/soroban-rpc/internal/methods/get_events.go b/cmd/soroban-rpc/internal/methods/get_events.go index 6eb705f2..0ce602fc 100644 --- a/cmd/soroban-rpc/internal/methods/get_events.go +++ b/cmd/soroban-rpc/internal/methods/get_events.go @@ -50,7 +50,7 @@ func (e *eventTypeSet) UnmarshalJSON(data []byte) error { } func (e eventTypeSet) MarshalJSON() ([]byte, error) { - var keys []string + keys := make([]string, 0, len(e)) for key := range e { keys = append(keys, key) } @@ -376,7 +376,7 @@ func (h eventsRPCHandler) getEvents(request GetEventsRequest) (GetEventsResponse results = append(results, info) } return GetEventsResponse{ - LatestLedger: uint32(latestLedger), + LatestLedger: latestLedger, Events: results, }, nil } diff --git a/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go b/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go index 30e05afa..86a8e48a 100644 --- a/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go +++ b/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go @@ -5,9 +5,10 @@ import ( "testing" "github.com/creachadair/jrpc2" - "github.com/stellar/go/xdr" "github.com/stretchr/testify/assert" + "github.com/stellar/go/xdr" + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/db" ) @@ -17,14 +18,11 @@ const ( expectedLatestLedgerHashBytes byte = 42 ) -type ConstantLedgerEntryReader struct { -} +type ConstantLedgerEntryReader struct{} -type ConstantLedgerEntryReaderTx struct { -} +type ConstantLedgerEntryReaderTx struct{} -type ConstantLedgerReader struct { -} +type ConstantLedgerReader struct{} func (entryReader *ConstantLedgerEntryReader) GetLatestLedgerSequence(ctx context.Context) (uint32, error) { return expectedLatestLedgerSequence, nil diff --git a/cmd/soroban-rpc/internal/methods/get_ledger_entries.go b/cmd/soroban-rpc/internal/methods/get_ledger_entries.go index 551e371a..f7c63b91 100644 --- a/cmd/soroban-rpc/internal/methods/get_ledger_entries.go +++ b/cmd/soroban-rpc/internal/methods/get_ledger_entries.go @@ -12,7 +12,8 @@ import ( "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/db" ) -var ErrLedgerTtlEntriesCannotBeQueriedDirectly = "ledger ttl entries cannot be queried directly" +//nolint:gochecknoglobals +var ErrLedgerTTLEntriesCannotBeQueriedDirectly = "ledger ttl entries cannot be queried directly" type GetLedgerEntriesRequest struct { Keys []string `json:"keys"` @@ -63,7 +64,7 @@ func NewGetLedgerEntriesHandler(logger *log.Entry, ledgerEntryReader db.LedgerEn Infof("could not provide ledger ttl entry %s at index %d from getLedgerEntries request", requestKey, i) return GetLedgerEntriesResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, - Message: ErrLedgerTtlEntriesCannotBeQueriedDirectly, + Message: ErrLedgerTTLEntriesCannotBeQueriedDirectly, } } ledgerKeys = append(ledgerKeys, ledgerKey) @@ -130,7 +131,7 @@ func NewGetLedgerEntriesHandler(logger *log.Entry, ledgerEntryReader db.LedgerEn response := GetLedgerEntriesResponse{ Entries: ledgerEntryResults, - LatestLedger: uint32(latestLedger), + LatestLedger: latestLedger, } return response, nil }) diff --git a/cmd/soroban-rpc/internal/methods/get_ledger_entry.go b/cmd/soroban-rpc/internal/methods/get_ledger_entry.go index a43e4b92..5ffd763a 100644 --- a/cmd/soroban-rpc/internal/methods/get_ledger_entry.go +++ b/cmd/soroban-rpc/internal/methods/get_ledger_entry.go @@ -47,7 +47,7 @@ func NewGetLedgerEntryHandler(logger *log.Entry, ledgerEntryReader db.LedgerEntr if key.Type == xdr.LedgerEntryTypeTtl { return GetLedgerEntryResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, - Message: ErrLedgerTtlEntriesCannotBeQueriedDirectly, + Message: ErrLedgerTTLEntriesCannotBeQueriedDirectly, } } diff --git a/cmd/soroban-rpc/internal/methods/get_transaction_test.go b/cmd/soroban-rpc/internal/methods/get_transaction_test.go index 960adf82..65ceea29 100644 --- a/cmd/soroban-rpc/internal/methods/get_transaction_test.go +++ b/cmd/soroban-rpc/internal/methods/get_transaction_test.go @@ -253,7 +253,6 @@ func txMeta(acctSeq uint32, successful bool) xdr.LedgerCloseMeta { } func txMetaWithEvents(acctSeq uint32, successful bool) xdr.LedgerCloseMeta { - meta := txMeta(acctSeq, successful) contractIDBytes, _ := hex.DecodeString("df06d62447fd25da07c0135eed7557e5a5497ee7d15b7fe345bd47e191d8f577") diff --git a/cmd/soroban-rpc/internal/methods/get_transactions.go b/cmd/soroban-rpc/internal/methods/get_transactions.go index b450622e..6fe48187 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions.go @@ -3,6 +3,7 @@ package methods import ( "context" "encoding/base64" + "errors" "fmt" "io" "strconv" @@ -11,7 +12,6 @@ import ( "github.com/creachadair/jrpc2/handler" "github.com/stellar/go/ingest" - "github.com/stellar/go/support/errors" "github.com/stellar/go/support/log" "github.com/stellar/go/toid" @@ -38,7 +38,11 @@ func (req GetTransactionsRequest) isValid(maxLimit uint, ledgerRange ledgerbucke return errors.New("startLedger and cursor cannot both be set") } } else if req.StartLedger < ledgerRange.FirstLedger.Sequence || req.StartLedger > ledgerRange.LastLedger.Sequence { - return errors.Errorf("start ledger must be between the oldest ledger: %d and the latest ledger: %d for this rpc instance.", ledgerRange.FirstLedger.Sequence, ledgerRange.LastLedger.Sequence) + return fmt.Errorf( + "start ledger must be between the oldest ledger: %d and the latest ledger: %d for this rpc instance", + ledgerRange.FirstLedger.Sequence, + ledgerRange.LastLedger.Sequence, + ) } if req.Pagination != nil && req.Pagination.Limit > maxLimit { @@ -148,7 +152,7 @@ LedgerLoop: } else if !found { return GetTransactionsResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, - Message: errors.Errorf("ledger close meta not found: %d", ledgerSeq).Error(), + Message: fmt.Sprintf("ledger close meta not found: %d", ledgerSeq), } } diff --git a/cmd/soroban-rpc/internal/methods/get_transactions_test.go b/cmd/soroban-rpc/internal/methods/get_transactions_test.go index f6f7fea2..b02cc750 100644 --- a/cmd/soroban-rpc/internal/methods/get_transactions_test.go +++ b/cmd/soroban-rpc/internal/methods/get_transactions_test.go @@ -2,13 +2,14 @@ package methods import ( "context" + "fmt" "testing" "github.com/creachadair/jrpc2" - "github.com/stellar/go/support/errors" + "github.com/stretchr/testify/assert" + "github.com/stellar/go/toid" "github.com/stellar/go/xdr" - "github.com/stretchr/testify/assert" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/db" ) @@ -71,17 +72,17 @@ func TestGetTransactions_DefaultLimit(t *testing.T) { } func TestGetTransactions_DefaultLimitExceedsLatestLedger(t *testing.T) { - mockDbReader := db.NewMockTransactionStore(NetworkPassphrase) - mockLedgerReader := db.NewMockLedgerReader(mockDbReader) + mockDBReader := db.NewMockTransactionStore(NetworkPassphrase) + mockLedgerReader := db.NewMockLedgerReader(mockDBReader) for i := 1; i <= 3; i++ { meta := createTestLedger(uint32(i)) - err := mockDbReader.InsertTransactions(meta) + err := mockDBReader.InsertTransactions(meta) assert.NoError(t, err) } handler := transactionsRPCHandler{ ledgerReader: mockLedgerReader, - dbReader: mockDbReader, + dbReader: mockDBReader, maxLimit: 100, defaultLimit: 10, networkPassphrase: NetworkPassphrase, @@ -102,21 +103,21 @@ func TestGetTransactions_DefaultLimitExceedsLatestLedger(t *testing.T) { assert.Equal(t, toid.New(3, 2, 1).String(), response.Cursor) // assert transactions result - assert.Equal(t, 6, len(response.Transactions)) + assert.Len(t, response.Transactions, 6) } func TestGetTransactions_CustomLimit(t *testing.T) { - mockDbReader := db.NewMockTransactionStore(NetworkPassphrase) - mockLedgerReader := db.NewMockLedgerReader(mockDbReader) + mockDBReader := db.NewMockTransactionStore(NetworkPassphrase) + mockLedgerReader := db.NewMockLedgerReader(mockDBReader) for i := 1; i <= 10; i++ { meta := createTestLedger(uint32(i)) - err := mockDbReader.InsertTransactions(meta) + err := mockDBReader.InsertTransactions(meta) assert.NoError(t, err) } handler := transactionsRPCHandler{ ledgerReader: mockLedgerReader, - dbReader: mockDbReader, + dbReader: mockDBReader, maxLimit: 100, defaultLimit: 10, networkPassphrase: NetworkPassphrase, @@ -140,23 +141,23 @@ func TestGetTransactions_CustomLimit(t *testing.T) { assert.Equal(t, toid.New(1, 2, 1).String(), response.Cursor) // assert transactions result - assert.Equal(t, 2, len(response.Transactions)) + assert.Len(t, response.Transactions, 2) assert.Equal(t, uint32(1), response.Transactions[0].Ledger) assert.Equal(t, uint32(1), response.Transactions[1].Ledger) } func TestGetTransactions_CustomLimitAndCursor(t *testing.T) { - mockDbReader := db.NewMockTransactionStore(NetworkPassphrase) - mockLedgerReader := db.NewMockLedgerReader(mockDbReader) + mockDBReader := db.NewMockTransactionStore(NetworkPassphrase) + mockLedgerReader := db.NewMockLedgerReader(mockDBReader) for i := 1; i <= 10; i++ { meta := createTestLedger(uint32(i)) - err := mockDbReader.InsertTransactions(meta) + err := mockDBReader.InsertTransactions(meta) assert.NoError(t, err) } handler := transactionsRPCHandler{ ledgerReader: mockLedgerReader, - dbReader: mockDbReader, + dbReader: mockDBReader, maxLimit: 100, defaultLimit: 10, networkPassphrase: NetworkPassphrase, @@ -208,7 +209,10 @@ func TestGetTransactions_InvalidStartLedger(t *testing.T) { } response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) - expectedErr := errors.Errorf("[%d] start ledger must be between the oldest ledger: 1 and the latest ledger: 3 for this rpc instance.", jrpc2.InvalidRequest) + expectedErr := fmt.Errorf( + "[%d] start ledger must be between the oldest ledger: 1 and the latest ledger: 3 for this rpc instance", + jrpc2.InvalidRequest, + ) assert.Equal(t, expectedErr.Error(), err.Error()) assert.Nil(t, response.Transactions) } @@ -239,7 +243,7 @@ func TestGetTransactions_LedgerNotFound(t *testing.T) { } response, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) - expectedErr := errors.Errorf("[%d] ledger close meta not found: 2", jrpc2.InvalidParams) + expectedErr := fmt.Errorf("[%d] ledger close meta not found: 2", jrpc2.InvalidParams) assert.Equal(t, expectedErr.Error(), err.Error()) assert.Nil(t, response.Transactions) } @@ -269,7 +273,7 @@ func TestGetTransactions_LimitGreaterThanMaxLimit(t *testing.T) { } _, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) - expectedErr := errors.Errorf("[%d] limit must not exceed 100", jrpc2.InvalidRequest) + expectedErr := fmt.Errorf("[%d] limit must not exceed 100", jrpc2.InvalidRequest) assert.Equal(t, expectedErr.Error(), err.Error()) } @@ -297,6 +301,6 @@ func TestGetTransactions_InvalidCursorString(t *testing.T) { } _, err := handler.getTransactionsByLedgerSequence(context.TODO(), request) - expectedErr := errors.Errorf("[%d] strconv.ParseInt: parsing \"abc\": invalid syntax", jrpc2.InvalidParams) + expectedErr := fmt.Errorf("[%d] strconv.ParseInt: parsing \"abc\": invalid syntax", jrpc2.InvalidParams) assert.Equal(t, expectedErr.Error(), err.Error()) } diff --git a/cmd/soroban-rpc/internal/methods/simulate_transaction.go b/cmd/soroban-rpc/internal/methods/simulate_transaction.go index 5b66836c..264f386b 100644 --- a/cmd/soroban-rpc/internal/methods/simulate_transaction.go +++ b/cmd/soroban-rpc/internal/methods/simulate_transaction.go @@ -132,7 +132,7 @@ func (l *LedgerEntryChange) FromXDRDiff(diff preflight.XDRDiff) error { return nil } -// LedgerEntryChange designates a change in a ledger entry. Before and After cannot be be omitted at the same time. +// LedgerEntryChange designates a change in a ledger entry. Before and After cannot be omitted at the same time. // If Before is omitted, it constitutes a creation, if After is omitted, it constitutes a delation. type LedgerEntryChange struct { Type LedgerEntryChangeType `json:"type"` @@ -154,7 +154,7 @@ type SimulateTransactionResponse struct { } type PreflightGetter interface { - GetPreflight(ctx context.Context, params preflight.PreflightGetterParameters) (preflight.Preflight, error) + GetPreflight(ctx context.Context, params preflight.GetterParameters) (preflight.Preflight, error) } // NewSimulateTransactionHandler returns a json rpc handler to run preflight simulations @@ -220,17 +220,17 @@ func NewSimulateTransactionHandler(logger *log.Entry, ledgerEntryReader db.Ledge } } - resource_config := preflight.DefaultResourceConfig() + resourceConfig := preflight.DefaultResourceConfig() if request.ResourceConfig != nil { - resource_config = *request.ResourceConfig + resourceConfig = *request.ResourceConfig } - params := preflight.PreflightGetterParameters{ + params := preflight.GetterParameters{ LedgerEntryReadTx: readTx, BucketListSize: bucketListSize, SourceAccount: sourceAccount, OperationBody: op.Body, Footprint: footprint, - ResourceConfig: resource_config, + ResourceConfig: resourceConfig, ProtocolVersion: protocolVersion, } result, err := getter.GetPreflight(ctx, params) diff --git a/cmd/soroban-rpc/internal/methods/simulate_transaction_test.go b/cmd/soroban-rpc/internal/methods/simulate_transaction_test.go index 0c3184b1..bde1e843 100644 --- a/cmd/soroban-rpc/internal/methods/simulate_transaction_test.go +++ b/cmd/soroban-rpc/internal/methods/simulate_transaction_test.go @@ -5,10 +5,11 @@ import ( "encoding/json" "testing" - "github.com/stellar/go/xdr" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/stellar/go/xdr" + "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/preflight" ) diff --git a/cmd/soroban-rpc/internal/network/backlogQ.go b/cmd/soroban-rpc/internal/network/backlogQ.go index b4b2791c..58d789c1 100644 --- a/cmd/soroban-rpc/internal/network/backlogQ.go +++ b/cmd/soroban-rpc/internal/network/backlogQ.go @@ -2,13 +2,13 @@ package network import ( "context" + "fmt" "math" "net/http" "sync/atomic" "github.com/creachadair/jrpc2" - "github.com/stellar/go/support/errors" "github.com/stellar/go/support/log" ) @@ -79,10 +79,8 @@ func (q *backlogHTTPQLimiter) ServeHTTP(res http.ResponseWriter, req *http.Reque } } return - } else { - if q.gauge != nil { - q.gauge.Inc() - } + } else if q.gauge != nil { + q.gauge.Inc() } defer func() { atomic.AddUint64(&q.pending, ^uint64(0)) @@ -110,11 +108,10 @@ func (q *backlogJrpcQLimiter) Handle(ctx context.Context, req *jrpc2.Request) (i q.logger.Infof("Backlog queue limiter reached the queue limit of %d executing concurrent rpc %s requests.", q.limit, req.Method()) } } - return nil, errors.Errorf("rpc queue for %s surpassed queue limit of %d requests", req.Method(), q.limit) - } else { - if q.gauge != nil { - q.gauge.Inc() - } + return nil, fmt.Errorf("rpc queue for %s surpassed queue limit of %d requests", req.Method(), q.limit) + } + if q.gauge != nil { + q.gauge.Inc() } defer func() { diff --git a/cmd/soroban-rpc/internal/network/backlogQ_test.go b/cmd/soroban-rpc/internal/network/backlogQ_test.go index fb738e56..ef35e4d9 100644 --- a/cmd/soroban-rpc/internal/network/backlogQ_test.go +++ b/cmd/soroban-rpc/internal/network/backlogQ_test.go @@ -81,7 +81,7 @@ func TestBacklogQueueLimiter_JrpcNonBlocking(t *testing.T) { for k := requestCount; k > 0; k-- { go func() { _, err := limiter.Handle(context.Background(), nil) - require.Nil(t, err) + require.NoError(t, err) wg.Done() }() } @@ -184,7 +184,7 @@ func TestBacklogQueueLimiter_JrpcBlocking(t *testing.T) { for i := uint64(0); i < queueSize/2; i++ { go func() { _, err := limiter.Handle(context.Background(), &jrpc2.Request{}) - require.Nil(t, err) + require.NoError(t, err) initialGroupBlocking.Done() }() } diff --git a/cmd/soroban-rpc/internal/network/requestdurationlimiter.go b/cmd/soroban-rpc/internal/network/requestdurationlimiter.go index c5af738f..c54350ca 100644 --- a/cmd/soroban-rpc/internal/network/requestdurationlimiter.go +++ b/cmd/soroban-rpc/internal/network/requestdurationlimiter.go @@ -121,6 +121,9 @@ func (w *bufferedResponseWriter) WriteOut(ctx context.Context, rw http.ResponseW } } +// TODO: refactor and simplify this function +// +//nolint:gocognit,cyclop func (q *httpRequestDurationLimiter) ServeHTTP(res http.ResponseWriter, req *http.Request) { if q.limitThreshold == RequestDurationLimiterNoLimit { // if specified max duration, pass-through diff --git a/cmd/soroban-rpc/internal/network/requestdurationlimiter_test.go b/cmd/soroban-rpc/internal/network/requestdurationlimiter_test.go index 9854d57c..b7644880 100644 --- a/cmd/soroban-rpc/internal/network/requestdurationlimiter_test.go +++ b/cmd/soroban-rpc/internal/network/requestdurationlimiter_test.go @@ -8,11 +8,10 @@ import ( "testing" "time" - "github.com/stretchr/testify/require" - "github.com/creachadair/jrpc2" "github.com/creachadair/jrpc2/handler" "github.com/creachadair/jrpc2/jhttp" + "github.com/stretchr/testify/require" ) type TestServerHandlerWrapper struct { @@ -54,7 +53,7 @@ func TestHTTPRequestDurationLimiter_Limiting(t *testing.T) { } n, err := res.Write([]byte{1, 2, 3}) require.Equal(t, 3, n) - require.Nil(t, err) + require.NoError(t, err) }, } warningCounter := TestingCounter{} diff --git a/cmd/soroban-rpc/internal/network/utils_test.go b/cmd/soroban-rpc/internal/network/utils_test.go index 8109a63d..471a2961 100644 --- a/cmd/soroban-rpc/internal/network/utils_test.go +++ b/cmd/soroban-rpc/internal/network/utils_test.go @@ -5,6 +5,7 @@ import ( "sync/atomic" "github.com/sirupsen/logrus" + "github.com/stellar/go/support/log" ) @@ -41,12 +42,15 @@ func makeTestLogCounter() *TestLogsCounter { out.entry.SetLevel(logrus.DebugLevel) return out } + func (te *TestLogsCounter) Entry() *log.Entry { return te.entry } + func (te *TestLogsCounter) Levels() []logrus.Level { return []logrus.Level{logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel, logrus.WarnLevel, logrus.InfoLevel, logrus.DebugLevel, logrus.TraceLevel} } + func (te *TestLogsCounter) Fire(e *logrus.Entry) error { te.writtenLogEntries[e.Level]++ return nil @@ -59,6 +63,7 @@ type TestingResponseWriter struct { func (t *TestingResponseWriter) Header() http.Header { return http.Header{} } + func (t *TestingResponseWriter) Write([]byte) (int, error) { return 0, nil } diff --git a/cmd/soroban-rpc/internal/preflight/pool.go b/cmd/soroban-rpc/internal/preflight/pool.go index c6f8b1fc..71ad82b4 100644 --- a/cmd/soroban-rpc/internal/preflight/pool.go +++ b/cmd/soroban-rpc/internal/preflight/pool.go @@ -23,11 +23,11 @@ type workerResult struct { type workerRequest struct { ctx context.Context - params PreflightParameters + params Parameters resultChan chan<- workerResult } -type PreflightWorkerPool struct { +type WorkerPool struct { ledgerEntryReader db.LedgerEntryReader networkPassphrase string enableDebug bool @@ -41,16 +41,26 @@ type PreflightWorkerPool struct { wg sync.WaitGroup } -func NewPreflightWorkerPool(daemon interfaces.Daemon, workerCount uint, jobQueueCapacity uint, enableDebug bool, ledgerEntryReader db.LedgerEntryReader, networkPassphrase string, logger *log.Entry) *PreflightWorkerPool { - preflightWP := PreflightWorkerPool{ - ledgerEntryReader: ledgerEntryReader, - networkPassphrase: networkPassphrase, - enableDebug: enableDebug, - logger: logger, - requestChan: make(chan workerRequest, jobQueueCapacity), +type WorkerPoolConfig struct { + Daemon interfaces.Daemon + WorkerCount uint + JobQueueCapacity uint + EnableDebug bool + LedgerEntryReader db.LedgerEntryReader + NetworkPassphrase string + Logger *log.Entry +} + +func NewPreflightWorkerPool(cfg WorkerPoolConfig) *WorkerPool { + preflightWP := WorkerPool{ + ledgerEntryReader: cfg.LedgerEntryReader, + networkPassphrase: cfg.NetworkPassphrase, + enableDebug: cfg.EnableDebug, + logger: cfg.Logger, + requestChan: make(chan workerRequest, cfg.JobQueueCapacity), } requestQueueMetric := prometheus.NewGaugeFunc(prometheus.GaugeOpts{ - Namespace: daemon.MetricsNamespace(), + Namespace: cfg.Daemon.MetricsNamespace(), Subsystem: "preflight_pool", Name: "queue_length", Help: "number of preflight requests in the queue", @@ -58,46 +68,46 @@ func NewPreflightWorkerPool(daemon interfaces.Daemon, workerCount uint, jobQueue return float64(len(preflightWP.requestChan)) }) preflightWP.concurrentRequestsMetric = prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: daemon.MetricsNamespace(), + Namespace: cfg.Daemon.MetricsNamespace(), Subsystem: "preflight_pool", Name: "concurrent_requests", Help: "number of preflight requests currently running", }) preflightWP.errorFullCounter = prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: daemon.MetricsNamespace(), + Namespace: cfg.Daemon.MetricsNamespace(), Subsystem: "preflight_pool", Name: "queue_full_errors", Help: "number of preflight full queue errors", }) preflightWP.durationMetric = prometheus.NewSummaryVec(prometheus.SummaryOpts{ - Namespace: daemon.MetricsNamespace(), + Namespace: cfg.Daemon.MetricsNamespace(), Subsystem: "preflight_pool", Name: "request_ledger_get_duration_seconds", Help: "preflight request duration broken down by status", Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, }, []string{"status", "type"}) preflightWP.ledgerEntriesFetchedMetric = prometheus.NewSummary(prometheus.SummaryOpts{ - Namespace: daemon.MetricsNamespace(), + Namespace: cfg.Daemon.MetricsNamespace(), Subsystem: "preflight_pool", Name: "request_ledger_entries_fetched", Help: "ledger entries fetched by simulate transaction calls", Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, }) - daemon.MetricsRegistry().MustRegister( + cfg.Daemon.MetricsRegistry().MustRegister( requestQueueMetric, preflightWP.concurrentRequestsMetric, preflightWP.errorFullCounter, preflightWP.durationMetric, preflightWP.ledgerEntriesFetchedMetric, ) - for i := uint(0); i < workerCount; i++ { + for range cfg.WorkerCount { preflightWP.wg.Add(1) go preflightWP.work() } return &preflightWP } -func (pwp *PreflightWorkerPool) work() { +func (pwp *WorkerPool) work() { defer pwp.wg.Done() for request := range pwp.requestChan { pwp.concurrentRequestsMetric.Inc() @@ -115,7 +125,7 @@ func (pwp *PreflightWorkerPool) work() { } } -func (pwp *PreflightWorkerPool) Close() { +func (pwp *WorkerPool) Close() { if !pwp.isClosed.CompareAndSwap(false, true) { // it was already closed return @@ -124,7 +134,7 @@ func (pwp *PreflightWorkerPool) Close() { pwp.wg.Wait() } -var PreflightQueueFullErr = errors.New("preflight queue full") +var ErrPreflightQueueFull = errors.New("preflight queue full") type metricsLedgerEntryWrapper struct { db.LedgerEntryReadTx @@ -140,14 +150,14 @@ func (m *metricsLedgerEntryWrapper) GetLedgerEntries(keys ...xdr.LedgerKey) ([]d return entries, err } -func (pwp *PreflightWorkerPool) GetPreflight(ctx context.Context, params PreflightGetterParameters) (Preflight, error) { +func (pwp *WorkerPool) GetPreflight(ctx context.Context, params GetterParameters) (Preflight, error) { if pwp.isClosed.Load() { return Preflight{}, errors.New("preflight worker pool is closed") } wrappedTx := metricsLedgerEntryWrapper{ LedgerEntryReadTx: params.LedgerEntryReadTx, } - preflightParams := PreflightParameters{ + preflightParams := Parameters{ Logger: pwp.logger, SourceAccount: params.SourceAccount, OpBody: params.OperationBody, @@ -178,6 +188,6 @@ func (pwp *PreflightWorkerPool) GetPreflight(ctx context.Context, params Preflig return Preflight{}, ctx.Err() default: pwp.errorFullCounter.Inc() - return Preflight{}, PreflightQueueFullErr + return Preflight{}, ErrPreflightQueueFull } } diff --git a/cmd/soroban-rpc/internal/preflight/preflight.go b/cmd/soroban-rpc/internal/preflight/preflight.go index b79be958..2c4485d8 100644 --- a/cmd/soroban-rpc/internal/preflight/preflight.go +++ b/cmd/soroban-rpc/internal/preflight/preflight.go @@ -87,7 +87,7 @@ func DefaultResourceConfig() ResourceConfig { } } -type PreflightGetterParameters struct { +type GetterParameters struct { LedgerEntryReadTx db.LedgerEntryReadTx BucketListSize uint64 SourceAccount xdr.AccountId @@ -97,7 +97,7 @@ type PreflightGetterParameters struct { ProtocolVersion uint32 } -type PreflightParameters struct { +type Parameters struct { Logger *log.Entry SourceAccount xdr.AccountId OpBody xdr.OperationBody @@ -159,18 +159,18 @@ func GoXDRDiffVector(xdrDiffVector C.xdr_diff_vector_t) []XDRDiff { return result } -func GetPreflight(_ context.Context, params PreflightParameters) (Preflight, error) { +func GetPreflight(_ context.Context, params Parameters) (Preflight, error) { switch params.OpBody.Type { case xdr.OperationTypeInvokeHostFunction: return getInvokeHostFunctionPreflight(params) case xdr.OperationTypeExtendFootprintTtl, xdr.OperationTypeRestoreFootprint: - return getFootprintTtlPreflight(params) + return getFootprintTTLPreflight(params) default: return Preflight{}, fmt.Errorf("unsupported operation type: %s", params.OpBody.Type.String()) } } -func getLedgerInfo(params PreflightParameters) (C.ledger_info_t, error) { +func getLedgerInfo(params Parameters) (C.ledger_info_t, error) { simulationLedgerSeq, err := getSimulationLedgerSeq(params.LedgerEntryReadTx) if err != nil { return C.ledger_info_t{}, err @@ -187,7 +187,7 @@ func getLedgerInfo(params PreflightParameters) (C.ledger_info_t, error) { return ledgerInfo, nil } -func getFootprintTtlPreflight(params PreflightParameters) (Preflight, error) { +func getFootprintTTLPreflight(params Parameters) (Preflight, error) { opBodyXDR, err := params.OpBody.MarshalBinary() if err != nil { return Preflight{}, err @@ -231,7 +231,7 @@ func getSimulationLedgerSeq(readTx db.LedgerEntryReadTx) (uint32, error) { return sequenceNumber, nil } -func getInvokeHostFunctionPreflight(params PreflightParameters) (Preflight, error) { +func getInvokeHostFunctionPreflight(params Parameters) (Preflight, error) { invokeHostFunctionXDR, err := params.OpBody.MustInvokeHostFunctionOp().MarshalBinary() if err != nil { return Preflight{}, err diff --git a/cmd/soroban-rpc/internal/preflight/preflight_test.go b/cmd/soroban-rpc/internal/preflight/preflight_test.go index 4e361605..5de512ca 100644 --- a/cmd/soroban-rpc/internal/preflight/preflight_test.go +++ b/cmd/soroban-rpc/internal/preflight/preflight_test.go @@ -8,17 +8,20 @@ import ( "runtime" "testing" + "github.com/stretchr/testify/require" + "github.com/stellar/go/network" "github.com/stellar/go/support/log" "github.com/stellar/go/xdr" - "github.com/stretchr/testify/require" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/daemon/interfaces" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/db" ) -var mockContractID = xdr.Hash{0xa, 0xb, 0xc} -var mockContractHash = xdr.Hash{0xd, 0xe, 0xf} +var ( + mockContractID = xdr.Hash{0xa, 0xb, 0xc} + mockContractHash = xdr.Hash{0xd, 0xe, 0xf} +) var contractCostParams = func() *xdr.ContractCostParams { var result xdr.ContractCostParams @@ -321,7 +324,7 @@ type preflightParametersDBConfig struct { disableCache bool } -func getPreflightParameters(t testing.TB, dbConfig *preflightParametersDBConfig) PreflightParameters { +func getPreflightParameters(t testing.TB, dbConfig *preflightParametersDBConfig) Parameters { var ledgerEntryReadTx db.LedgerEntryReadTx if dbConfig != nil { entryReader := db.NewLedgerEntryReader(dbConfig.dbInstance) @@ -338,11 +341,12 @@ func getPreflightParameters(t testing.TB, dbConfig *preflightParametersDBConfig) require.NoError(t, err) } argSymbol := xdr.ScSymbol("world") - params := PreflightParameters{ + params := Parameters{ EnableDebug: true, Logger: log.New(), SourceAccount: xdr.MustAddress("GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H"), - OpBody: xdr.OperationBody{Type: xdr.OperationTypeInvokeHostFunction, + OpBody: xdr.OperationBody{ + Type: xdr.OperationTypeInvokeHostFunction, InvokeHostFunctionOp: &xdr.InvokeHostFunctionOp{ HostFunction: xdr.HostFunction{ Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, @@ -360,7 +364,8 @@ func getPreflightParameters(t testing.TB, dbConfig *preflightParametersDBConfig) }, }, }, - }}, + }, + }, NetworkPassphrase: "foo", LedgerEntryReadTx: ledgerEntryReadTx, BucketListSize: 200, diff --git a/cmd/soroban-rpc/internal/util/panicgroup_test.go b/cmd/soroban-rpc/internal/util/panicgroup_test.go index 63c42206..64ed7a16 100644 --- a/cmd/soroban-rpc/internal/util/panicgroup_test.go +++ b/cmd/soroban-rpc/internal/util/panicgroup_test.go @@ -7,8 +7,9 @@ import ( "time" "github.com/sirupsen/logrus" - "github.com/stellar/go/support/log" "github.com/stretchr/testify/require" + + "github.com/stellar/go/support/log" ) func TestTrivialPanicGroup(t *testing.T) { @@ -34,18 +35,22 @@ func makeTestLogCounter() *TestLogsCounter { out.entry.SetLevel(logrus.DebugLevel) return out } + func (te *TestLogsCounter) Entry() *log.Entry { return te.entry } + func (te *TestLogsCounter) Levels() []logrus.Level { return []logrus.Level{logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel, logrus.WarnLevel, logrus.InfoLevel, logrus.DebugLevel, logrus.TraceLevel} } + func (te *TestLogsCounter) Fire(e *logrus.Entry) error { te.mu.Lock() defer te.mu.Unlock() te.writtenLogEntries[e.Level]++ return nil } + func (te *TestLogsCounter) GetLevel(i int) int { te.mu.Lock() defer te.mu.Unlock() diff --git a/cmd/soroban-rpc/main.go b/cmd/soroban-rpc/main.go index 002a0ee8..84fa9116 100644 --- a/cmd/soroban-rpc/main.go +++ b/cmd/soroban-rpc/main.go @@ -49,8 +49,10 @@ func main() { if branch == "main" { branch = "" } + //nolint:forbidigo fmt.Printf("soroban-rpc %s (%s) %s\n", config.Version, config.CommitHash, branch) } + //nolint:forbidigo fmt.Printf("stellar-xdr %s\n", goxdr.CommitHash) }, }