diff --git a/CHANGELOG.md b/CHANGELOG.md index d5a46901d..e5bac4406 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ * [\#1231](https://github.com/cosmos/relayer/pull/1231) Reduce get bech32 prefix when get signer. * [\#1302](https://github.com/cosmos/relayer/pull/1302) Avoid packet get relayed when estimated gas is higher than max gas. * [\#1303](https://github.com/cosmos/relayer/pull/1303) Add missing max gas amount on txf to avoid estimate less gas when simualte runTx. +* [\#1324](https://github.com/cosmos/relayer/pull/1324) Add log-level in global config. +* [\#1325](https://github.com/cosmos/relayer/pull/1325) Ignore only file not exist error when loadConfigFile. ## v0.9.3 diff --git a/cmd/appstate.go b/cmd/appstate.go index 738e9af40..44aff4736 100644 --- a/cmd/appstate.go +++ b/cmd/appstate.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "io/fs" "os" "path" @@ -30,6 +31,22 @@ type appState struct { config *Config } +func (a *appState) initLogger(configLogLevel string) error { + logLevel := a.viper.GetString("log-level") + if a.viper.GetBool("debug") { + logLevel = "debug" + } else if logLevel == "" { + logLevel = configLogLevel + } + log, err := newRootLogger(a.viper.GetString("log-format"), logLevel) + if err != nil { + return err + } + + a.log = log + return nil +} + func (a *appState) configPath() string { return path.Join(a.homePath, "config", "config.yaml") } @@ -40,7 +57,10 @@ func (a *appState) loadConfigFile(ctx context.Context) error { if _, err := os.Stat(cfgPath); err != nil { // don't return error if file doesn't exist - return nil + if errors.Is(err, fs.ErrNotExist) { + err = nil + } + return err } // read the config file bytes @@ -56,6 +76,10 @@ func (a *appState) loadConfigFile(ctx context.Context) error { return fmt.Errorf("error unmarshalling config: %w", err) } + if a.log == nil { + a.initLogger(cfgWrapper.Global.LogLevel) + } + // retrieve the runtime configuration from the disk configuration. newCfg, err := cfgWrapper.RuntimeConfig(ctx, a) if err != nil { diff --git a/cmd/config.go b/cmd/config.go index 80ae95e4c..a6337ed94 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -492,6 +492,7 @@ type GlobalConfig struct { Timeout string `yaml:"timeout" json:"timeout"` Memo string `yaml:"memo" json:"memo"` LightCacheSize int `yaml:"light-cache-size" json:"light-cache-size"` + LogLevel string `yaml:"log-level" json:"log-level"` } // newDefaultGlobalConfig returns a global config with defaults set @@ -501,6 +502,7 @@ func newDefaultGlobalConfig(memo string) GlobalConfig { Timeout: "10s", LightCacheSize: 20, Memo: memo, + LogLevel: "info", } } diff --git a/cmd/flags.go b/cmd/flags.go index d8d4b187c..f4d2011a2 100644 --- a/cmd/flags.go +++ b/cmd/flags.go @@ -32,6 +32,7 @@ const ( flagUpdateAfterExpiry = "update-after-expiry" flagUpdateAfterMisbehaviour = "update-after-misbehaviour" flagClientTrustingPeriod = "client-tp" + flagClientUnbondingPeriod = "client-unbonding-period" flagOverride = "override" flagSrcPort = "src-port" flagDstPort = "dst-port" @@ -332,6 +333,14 @@ func channelParameterFlags(v *viper.Viper, cmd *cobra.Command) *cobra.Command { return srcPortFlag(v, dstPortFlag(v, versionFlag(v, orderFlag(v, cmd)))) } +func clientUnbondingPeriodFlag(v *viper.Viper, cmd *cobra.Command) *cobra.Command { + cmd.Flags().Duration(flagClientUnbondingPeriod, 0, "custom unbonding period for client state. This is useful when you need to create a new client matching an older client state") + if err := v.BindPFlag(flagClientUnbondingPeriod, cmd.Flags().Lookup(flagClientUnbondingPeriod)); err != nil { + panic(err) + } + return cmd +} + func overrideFlag(v *viper.Viper, cmd *cobra.Command) *cobra.Command { cmd.Flags().Bool(flagOverride, false, "option to not reuse existing client or channel") if err := v.BindPFlag(flagOverride, cmd.Flags().Lookup(flagOverride)); err != nil { diff --git a/cmd/root.go b/cmd/root.go index 1a6cfc3d3..52e316055 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -73,17 +73,15 @@ func NewRootCmd(log *zap.Logger) *cobra.Command { rootCmd.PersistentPreRunE = func(cmd *cobra.Command, _ []string) error { // Inside persistent pre-run because this takes effect after flags are parsed. - if log == nil { - log, err := newRootLogger(a.viper.GetString("log-format"), a.viper.GetBool("debug")) - if err != nil { - return err - } - - a.log = log - } - // reads `homeDir/config/config.yaml` into `a.Config` - return a.loadConfigFile(rootCmd.Context()) + if err := a.loadConfigFile(rootCmd.Context()); err != nil { + return err + } + // Inside persistent pre-run because this takes effect after flags are parsed. + if a.log == nil { + a.initLogger("") + } + return nil } rootCmd.PersistentPostRun = func(cmd *cobra.Command, _ []string) { @@ -108,6 +106,12 @@ func NewRootCmd(log *zap.Logger) *cobra.Command { panic(err) } + // Register --log-level flag + rootCmd.PersistentFlags().String("log-level", "", "log level format (info, debug, warn, error, panic or fatal)") + if err := a.viper.BindPFlag("log-level", rootCmd.PersistentFlags().Lookup("log-level")); err != nil { + panic(err) + } + // Register subcommands rootCmd.AddCommand( configCmd(a), @@ -171,7 +175,7 @@ func Execute() { } } -func newRootLogger(format string, debug bool) (*zap.Logger, error) { +func newRootLogger(format string, logLevel string) (*zap.Logger, error) { config := zap.NewProductionEncoderConfig() config.EncodeTime = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) { encoder.AppendString(ts.UTC().Format("2006-01-02T15:04:05.000000Z07:00")) @@ -191,8 +195,17 @@ func newRootLogger(format string, debug bool) (*zap.Logger, error) { } level := zap.InfoLevel - if debug { + switch logLevel { + case "debug": level = zap.DebugLevel + case "warn": + level = zapcore.WarnLevel + case "error": + level = zapcore.ErrorLevel + case "panic": + level = zapcore.PanicLevel + case "fatal": + level = zapcore.FatalLevel } return zap.New(zapcore.NewCore( enc, diff --git a/cmd/tx.go b/cmd/tx.go index 309d3d06d..7775a0278 100644 --- a/cmd/tx.go +++ b/cmd/tx.go @@ -143,6 +143,11 @@ func createClientCmd(a *appState) *cobra.Command { return err } + overrideUnbondingPeriod, err := cmd.Flags().GetDuration(flagClientUnbondingPeriod) + if err != nil { + return err + } + override, err := cmd.Flags().GetBool(flagOverride) if err != nil { return err @@ -210,7 +215,7 @@ func createClientCmd(a *appState) *cobra.Command { return err } - clientID, err := relayer.CreateClient(cmd.Context(), src, dst, srcUpdateHeader, dstUpdateHeader, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, a.config.memo(cmd)) + clientID, err := relayer.CreateClient(cmd.Context(), src, dst, srcUpdateHeader, dstUpdateHeader, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, overrideUnbondingPeriod, a.config.memo(cmd)) if err != nil { return err } @@ -231,6 +236,7 @@ func createClientCmd(a *appState) *cobra.Command { } cmd = clientParameterFlags(a.viper, cmd) + cmd = clientUnbondingPeriodFlag(a.viper, cmd) cmd = overrideFlag(a.viper, cmd) cmd = memoFlag(a.viper, cmd) return cmd diff --git a/examples/config_EXAMPLE.yaml b/examples/config_EXAMPLE.yaml index dd4ad343d..900d9d608 100644 --- a/examples/config_EXAMPLE.yaml +++ b/examples/config_EXAMPLE.yaml @@ -3,6 +3,7 @@ global: timeout: 10s memo: "" light-cache-size: 20 + log-level: "info" chains: cosmoshub: type: cosmos diff --git a/relayer/chain.go b/relayer/chain.go index 03a1c27cb..76d26433e 100644 --- a/relayer/chain.go +++ b/relayer/chain.go @@ -96,8 +96,8 @@ func (c *Chain) GetSelfVersion() uint64 { } // GetTrustingPeriod returns the trusting period for the chain -func (c *Chain) GetTrustingPeriod(ctx context.Context) (time.Duration, error) { - return c.ChainProvider.TrustingPeriod(ctx) +func (c *Chain) GetTrustingPeriod(ctx context.Context, overrideUnbondingPeriod time.Duration) (time.Duration, error) { + return c.ChainProvider.TrustingPeriod(ctx, overrideUnbondingPeriod) } func (c *Chain) String() string { diff --git a/relayer/chains/cosmos/provider.go b/relayer/chains/cosmos/provider.go index 3bb7f4448..f7c82b9dd 100644 --- a/relayer/chains/cosmos/provider.go +++ b/relayer/chains/cosmos/provider.go @@ -237,12 +237,17 @@ func (cc *CosmosProvider) AccountFromKeyOrAddress(keyOrAddress string) (out sdk. return } -func (cc *CosmosProvider) TrustingPeriod(ctx context.Context) (time.Duration, error) { +func (cc *CosmosProvider) TrustingPeriod(ctx context.Context, overrideUnbondingPeriod time.Duration) (time.Duration, error) { - unbondingTime, err := cc.QueryUnbondingPeriod(ctx) - if err != nil { - return 0, err + unbondingTime := overrideUnbondingPeriod + var err error + if unbondingTime == 0 { + unbondingTime, err = cc.QueryUnbondingPeriod(ctx) + if err != nil { + return 0, err + } } + // We want the trusting period to be 85% of the unbonding time. // Go mentions that the time.Duration type can track approximately 290 years. // We don't want to lose precision if the duration is a very long duration diff --git a/relayer/chains/penumbra/provider.go b/relayer/chains/penumbra/provider.go index e1cf6ab20..cade2b968 100644 --- a/relayer/chains/penumbra/provider.go +++ b/relayer/chains/penumbra/provider.go @@ -208,7 +208,7 @@ func (cc *PenumbraProvider) Address() (string, error) { return out, err } -func (cc *PenumbraProvider) TrustingPeriod(ctx context.Context) (time.Duration, error) { +func (cc *PenumbraProvider) TrustingPeriod(ctx context.Context, overrideUnbondingPeriod time.Duration) (time.Duration, error) { // TODO return time.Hour * 2, nil /* diff --git a/relayer/client.go b/relayer/client.go index 6b5c3ae1a..89320f43b 100644 --- a/relayer/client.go +++ b/relayer/client.go @@ -55,12 +55,15 @@ func (c *Chain) CreateClients(ctx context.Context, dst *Chain, allowUpdateAfterE return "", "", err } + // overriding the unbonding period should only be possible when creating single clients at a time (CreateClient) + var overrideUnbondingPeriod = time.Duration(0) + var clientSrc, clientDst string eg, egCtx := errgroup.WithContext(ctx) eg.Go(func() error { var err error // Create client on src for dst if the client id is unspecified - clientSrc, err = CreateClient(egCtx, c, dst, srcUpdateHeader, dstUpdateHeader, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, memo) + clientSrc, err = CreateClient(egCtx, c, dst, srcUpdateHeader, dstUpdateHeader, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, overrideUnbondingPeriod, memo) if err != nil { return fmt.Errorf("failed to create client on src chain{%s}: %w", c.ChainID(), err) } @@ -70,7 +73,7 @@ func (c *Chain) CreateClients(ctx context.Context, dst *Chain, allowUpdateAfterE eg.Go(func() error { var err error // Create client on dst for src if the client id is unspecified - clientDst, err = CreateClient(egCtx, dst, c, dstUpdateHeader, srcUpdateHeader, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, memo) + clientDst, err = CreateClient(egCtx, dst, c, dstUpdateHeader, srcUpdateHeader, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, overrideUnbondingPeriod, memo) if err != nil { return fmt.Errorf("failed to create client on dst chain{%s}: %w", dst.ChainID(), err) } @@ -102,6 +105,7 @@ func CreateClient( allowUpdateAfterMisbehaviour bool, override bool, customClientTrustingPeriod time.Duration, + overrideUnbondingPeriod time.Duration, memo string) (string, error) { // If a client ID was specified in the path and override is not set, ensure the client exists. if !override && src.PathEnd.ClientID != "" { @@ -122,7 +126,7 @@ func CreateClient( if tp == 0 { if err := retry.Do(func() error { var err error - tp, err = dst.GetTrustingPeriod(ctx) + tp, err = dst.GetTrustingPeriod(ctx, overrideUnbondingPeriod) if err != nil { return fmt.Errorf("failed to get trusting period for chain{%s}: %w", dst.ChainID(), err) } @@ -143,17 +147,19 @@ func CreateClient( zap.Duration("trust_period", tp), ) - // Query the unbonding period for dst and retry if the query fails - var ubdPeriod time.Duration - if err := retry.Do(func() error { - var err error - ubdPeriod, err = dst.ChainProvider.QueryUnbondingPeriod(ctx) - if err != nil { - return fmt.Errorf("failed to query unbonding period for chain{%s}: %w", dst.ChainID(), err) + ubdPeriod := overrideUnbondingPeriod + if ubdPeriod == 0 { + // Query the unbonding period for dst and retry if the query fails + if err := retry.Do(func() error { + var err error + ubdPeriod, err = dst.ChainProvider.QueryUnbondingPeriod(ctx) + if err != nil { + return fmt.Errorf("failed to query unbonding period for chain{%s}: %w", dst.ChainID(), err) + } + return nil + }, retry.Context(ctx), RtyAtt, RtyDel, RtyErr); err != nil { + return "", err } - return nil - }, retry.Context(ctx), RtyAtt, RtyDel, RtyErr); err != nil { - return "", err } // We want to create a light client on the src chain which tracks the state of the dst chain. diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index 35fa90e27..b962e8735 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -404,7 +404,7 @@ type ChainProvider interface { Key() string Address() (string, error) Timeout() string - TrustingPeriod(ctx context.Context) (time.Duration, error) + TrustingPeriod(ctx context.Context, overrideUnbondingPeriod time.Duration) (time.Duration, error) WaitForNBlocks(ctx context.Context, n int64) error Sprint(toPrint proto.Message) (string, error)