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/tx.go b/cmd/tx.go index 041076a25..bb59ec645 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/relayer/chain.go b/relayer/chain.go index a23229bd8..6dafd2a6e 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 a8041466d..b3a75026d 100644 --- a/relayer/chains/cosmos/provider.go +++ b/relayer/chains/cosmos/provider.go @@ -225,11 +225,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 + } + } else { + unbondingTime = overrideUnbondingPeriod } // We want the trusting period to be 85% of the unbonding time. // Go mentions that the time.Duration type can track approximately 290 years. diff --git a/relayer/chains/penumbra/provider.go b/relayer/chains/penumbra/provider.go index fc680a41e..19176559d 100644 --- a/relayer/chains/penumbra/provider.go +++ b/relayer/chains/penumbra/provider.go @@ -196,7 +196,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 2330b262b..763bfa60b 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 d5bd7abd7..ab34b32d0 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)