diff --git a/cmd/flags.go b/cmd/flags.go index bf43350e9..90b6eeb87 100644 --- a/cmd/flags.go +++ b/cmd/flags.go @@ -32,6 +32,7 @@ const ( flagClientTrustingPeriod = "client-tp" flagClientUnbondingPeriod = "client-unbonding-period" flagClientTrustingPeriodPercentage = "client-tp-percentage" + flagMaxClockDrift = "max-clock-drift" flagOverride = "override" flagSrcPort = "src-port" flagDstPort = "dst-port" @@ -331,6 +332,8 @@ func clientParameterFlags(v *viper.Viper, cmd *cobra.Command) *cobra.Command { 85, "custom light client trusting period percentage ex. 66 (default: 85); this flag overrides the client-tp flag", ) + cmd.Flags().Duration(flagMaxClockDrift, (10 * time.Minute), + "custom max clock drift for client(s)") if err := v.BindPFlag(flagUpdateAfterExpiry, cmd.Flags().Lookup(flagUpdateAfterExpiry)); err != nil { panic(err) @@ -344,6 +347,9 @@ func clientParameterFlags(v *viper.Viper, cmd *cobra.Command) *cobra.Command { panic(err) } + if err := v.BindPFlag(flagMaxClockDrift, cmd.Flags().Lookup(flagMaxClockDrift)); err != nil { + panic(err) + } if err := v.BindPFlag(flagClientTrustingPeriodPercentage, cmd.Flags().Lookup(flagClientTrustingPeriodPercentage)); err != nil { panic(err) } diff --git a/cmd/tx.go b/cmd/tx.go index fba474708..69354f92e 100644 --- a/cmd/tx.go +++ b/cmd/tx.go @@ -4,10 +4,11 @@ import ( "context" "errors" "fmt" - "github.com/avast/retry-go/v4" "strings" "time" + "github.com/avast/retry-go/v4" + sdk "github.com/cosmos/cosmos-sdk/types" chantypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" "github.com/cosmos/relayer/v2/relayer" @@ -79,6 +80,11 @@ func createClientsCmd(a *appState) *cobra.Command { return err } + maxClockDrift, err := cmd.Flags().GetDuration(flagMaxClockDrift) + if err != nil { + return err + } + customClientTrustingPeriodPercentage, err := cmd.Flags().GetInt64(flagClientTrustingPeriodPercentage) if err != nil { return err @@ -111,6 +117,7 @@ func createClientsCmd(a *appState) *cobra.Command { allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, + maxClockDrift, customClientTrustingPeriodPercentage, a.config.memo(cmd), ) @@ -173,6 +180,11 @@ func createClientCmd(a *appState) *cobra.Command { return err } + maxClockDrift, err := cmd.Flags().GetDuration(flagMaxClockDrift) + if err != nil { + return err + } + src, ok := a.config.Chains[args[0]] if !ok { return errChainNotFound(args[0]) @@ -250,8 +262,9 @@ func createClientCmd(a *appState) *cobra.Command { allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, - customClientTrustingPeriodPercentage, overrideUnbondingPeriod, + maxClockDrift, + customClientTrustingPeriodPercentage, a.config.memo(cmd), ) if err != nil { @@ -360,7 +373,7 @@ func createConnectionCmd(a *appState) *cobra.Command { cmd := &cobra.Command{ Use: "connection path_name", Aliases: []string{"conn"}, - Short: "create a connection between two configured chains with a configured path", + Short: "create a connection between two configured chains with a configured path; if existing client does not exist, it will create one", Long: strings.TrimSpace(`Create or repair a connection between two IBC-connected networks along a specific path.`, ), @@ -413,6 +426,11 @@ $ %s tx conn demo-path --timeout 5s`, return err } + maxClockDrift, err := cmd.Flags().GetDuration(flagMaxClockDrift) + if err != nil { + return err + } + // ensure that keys exist if exists := c[src].ChainProvider.KeyExists(c[src].ChainProvider.Key()); !exists { return fmt.Errorf("key %s not found on src chain %s", c[src].ChainProvider.Key(), c[src].ChainID()) @@ -437,6 +455,7 @@ $ %s tx conn demo-path --timeout 5s`, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, + maxClockDrift, customClientTrustingPeriodPercentage, memo, ) @@ -723,6 +742,11 @@ $ %s tx connect demo-path --src-port transfer --dst-port transfer --order unorde return err } + maxClockDrift, err := cmd.Flags().GetDuration(flagMaxClockDrift) + if err != nil { + return err + } + // ensure that keys exist if exists := c[src].ChainProvider.KeyExists(c[src].ChainProvider.Key()); !exists { return fmt.Errorf("key %s not found on src chain %s", c[src].ChainProvider.Key(), c[src].ChainID()) @@ -747,6 +771,7 @@ $ %s tx connect demo-path --src-port transfer --dst-port transfer --order unorde allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, + maxClockDrift, customClientTrustingPeriodPercentage, memo, ) diff --git a/relayer/chains/cosmos/tx.go b/relayer/chains/cosmos/tx.go index 9897b0543..115b24be9 100644 --- a/relayer/chains/cosmos/tx.go +++ b/relayer/chains/cosmos/tx.go @@ -1557,7 +1557,8 @@ func (cc *CosmosProvider) NewClientState( dstChainID string, dstUpdateHeader provider.IBCHeader, dstTrustingPeriod, - dstUbdPeriod time.Duration, + dstUbdPeriod, + maxClockDrift time.Duration, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour bool, ) (ibcexported.ClientState, error) { @@ -1569,7 +1570,7 @@ func (cc *CosmosProvider) NewClientState( TrustLevel: tmclient.NewFractionFromTm(light.DefaultTrustLevel), TrustingPeriod: dstTrustingPeriod, UnbondingPeriod: dstUbdPeriod, - MaxClockDrift: time.Minute * 10, + MaxClockDrift: maxClockDrift, FrozenHeight: clienttypes.ZeroHeight(), LatestHeight: clienttypes.Height{ RevisionNumber: revisionNumber, diff --git a/relayer/chains/penumbra/tx.go b/relayer/chains/penumbra/tx.go index c07d7d299..4a3a1632e 100644 --- a/relayer/chains/penumbra/tx.go +++ b/relayer/chains/penumbra/tx.go @@ -2017,7 +2017,8 @@ func (cc *PenumbraProvider) NewClientState( dstChainID string, dstUpdateHeader provider.IBCHeader, dstTrustingPeriod, - dstUbdPeriod time.Duration, + dstUbdPeriod, + maxClockDrift time.Duration, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour bool, ) (ibcexported.ClientState, error) { @@ -2029,7 +2030,7 @@ func (cc *PenumbraProvider) NewClientState( TrustLevel: tmclient.NewFractionFromTm(light.DefaultTrustLevel), TrustingPeriod: dstTrustingPeriod, UnbondingPeriod: dstUbdPeriod, - MaxClockDrift: time.Minute * 10, + MaxClockDrift: maxClockDrift, FrozenHeight: clienttypes.ZeroHeight(), LatestHeight: clienttypes.Height{ RevisionNumber: revisionNumber, diff --git a/relayer/client.go b/relayer/client.go index 393875b7b..de8876f91 100644 --- a/relayer/client.go +++ b/relayer/client.go @@ -3,6 +3,8 @@ package relayer import ( "context" "fmt" + "time" + "github.com/avast/retry-go/v4" codectypes "github.com/cosmos/cosmos-sdk/codec/types" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" @@ -11,11 +13,18 @@ import ( "github.com/cosmos/relayer/v2/relayer/provider" "go.uber.org/zap" "golang.org/x/sync/errgroup" - "time" ) // CreateClients creates clients for src on dst and dst on src if the client ids are unspecified. -func (c *Chain) CreateClients(ctx context.Context, dst *Chain, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override bool, customClientTrustingPeriod time.Duration, customClientTrustingPeriodPercentage int64, memo string) (string, string, error) { +func (c *Chain) CreateClients(ctx context.Context, + dst *Chain, + allowUpdateAfterExpiry, + allowUpdateAfterMisbehaviour, + override bool, + customClientTrustingPeriod, + maxClockDrift time.Duration, + customClientTrustingPeriodPercentage int64, + memo string) (string, string, error) { // Query the latest heights on src and dst and retry if the query fails var srch, dsth int64 if err := retry.Do(func() error { @@ -62,7 +71,12 @@ func (c *Chain) CreateClients(ctx context.Context, dst *Chain, allowUpdateAfterE 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, customClientTrustingPeriodPercentage, overrideUnbondingPeriod, memo) + clientSrc, err = CreateClient(egCtx, c, dst, + srcUpdateHeader, dstUpdateHeader, + allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, + override, customClientTrustingPeriod, + overrideUnbondingPeriod, maxClockDrift, + customClientTrustingPeriodPercentage, memo) if err != nil { return fmt.Errorf("failed to create client on src chain{%s}: %w", c.ChainID(), err) } @@ -72,7 +86,12 @@ 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, customClientTrustingPeriodPercentage, overrideUnbondingPeriod, memo) + clientDst, err = CreateClient(egCtx, dst, c, + dstUpdateHeader, srcUpdateHeader, + allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, + override, customClientTrustingPeriod, + overrideUnbondingPeriod, maxClockDrift, + customClientTrustingPeriodPercentage, memo) if err != nil { return fmt.Errorf("failed to create client on dst chain{%s}: %w", dst.ChainID(), err) } @@ -100,12 +119,13 @@ func CreateClient( ctx context.Context, src, dst *Chain, srcUpdateHeader, dstUpdateHeader provider.IBCHeader, - allowUpdateAfterExpiry bool, - allowUpdateAfterMisbehaviour bool, + allowUpdateAfterExpiry, + allowUpdateAfterMisbehaviour, override bool, - customClientTrustingPeriod time.Duration, + customClientTrustingPeriod, + overrideUnbondingPeriod, + maxClockDrift time.Duration, customClientTrustingPeriodPercentage int64, - 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 != "" { @@ -164,7 +184,7 @@ func CreateClient( // We want to create a light client on the src chain which tracks the state of the dst chain. // So we build a new client state from dst and attempt to use this for creating the light client on src. - clientState, err := dst.ChainProvider.NewClientState(dst.ChainID(), dstUpdateHeader, tp, ubdPeriod, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour) + clientState, err := dst.ChainProvider.NewClientState(dst.ChainID(), dstUpdateHeader, tp, ubdPeriod, maxClockDrift, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour) if err != nil { return "", fmt.Errorf("failed to create new client state for chain{%s}: %w", dst.ChainID(), err) } diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index df2b3e6dc..c68587a61 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -232,7 +232,7 @@ type ChainProvider interface { Init(ctx context.Context) error // [Begin] Client IBC message assembly functions - NewClientState(dstChainID string, dstIBCHeader IBCHeader, dstTrustingPeriod, dstUbdPeriod time.Duration, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour bool) (ibcexported.ClientState, error) + NewClientState(dstChainID string, dstIBCHeader IBCHeader, dstTrustingPeriod, dstUbdPeriod, maxClockDrift time.Duration, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour bool) (ibcexported.ClientState, error) MsgCreateClient(clientState ibcexported.ClientState, consensusState ibcexported.ConsensusState) (RelayerMessage, error)