@@ -2,11 +2,14 @@ package cmd
2
2
3
3
import (
4
4
"fmt"
5
+ "strconv"
5
6
"strings"
6
7
"time"
7
8
9
+ "github.com/avast/retry-go"
8
10
"github.com/cosmos/cosmos-sdk/client/flags"
9
11
sdk "github.com/cosmos/cosmos-sdk/types"
12
+ "github.com/cosmos/ibc-go/v2/modules/core/exported"
10
13
"github.com/cosmos/relayer/relayer"
11
14
"github.com/spf13/cobra"
12
15
)
@@ -29,16 +32,19 @@ Most of these commands take a [path] argument. Make sure:
29
32
linkCmd (),
30
33
linkThenStartCmd (),
31
34
relayMsgsCmd (),
35
+ relayMsgCmd (),
32
36
relayAcksCmd (),
33
37
xfersend (),
34
38
flags .LineBreak ,
35
39
createClientsCmd (),
40
+ createClientCmd (),
36
41
updateClientsCmd (),
37
42
upgradeClientsCmd (),
38
43
//upgradeChainCmd(),
39
44
createConnectionCmd (),
40
45
closeChannelCmd (),
41
46
flags .LineBreak ,
47
+
42
48
//sendCmd(),
43
49
)
44
50
@@ -146,6 +152,95 @@ func createClientsCmd() *cobra.Command {
146
152
return overrideFlag (clientParameterFlags (cmd ))
147
153
}
148
154
155
+ func createClientCmd () * cobra.Command {
156
+ cmd := & cobra.Command {
157
+ Use : "client [src-chain-id] [dst-chain-id] [path-name]" ,
158
+ Short : "create a client between two configured chains with a configured path" ,
159
+ Long : "Creates a working ibc client for chain configured on each end of the" +
160
+ " path by querying headers from each chain and then sending the corresponding create-client messages" ,
161
+ Args : cobra .ExactArgs (3 ),
162
+ Example : strings .TrimSpace (fmt .Sprintf (`$ %s transact clients demo-path` , appName )),
163
+ RunE : func (cmd * cobra.Command , args []string ) error {
164
+ allowUpdateAfterExpiry , err := cmd .Flags ().GetBool (flagUpdateAfterExpiry )
165
+ if err != nil {
166
+ return err
167
+ }
168
+
169
+ allowUpdateAfterMisbehaviour , err := cmd .Flags ().GetBool (flagUpdateAfterMisbehaviour )
170
+ if err != nil {
171
+ return err
172
+ }
173
+
174
+ override , err := cmd .Flags ().GetBool (flagOverride )
175
+ if err != nil {
176
+ return err
177
+ }
178
+
179
+ src := args [0 ]
180
+ dst := args [1 ]
181
+ c , err := config .Chains .Gets (src , dst )
182
+ if err != nil {
183
+ return err
184
+ }
185
+
186
+ pathName := args [2 ]
187
+ path , err := config .Paths .Get (pathName )
188
+ if err != nil {
189
+ return err
190
+ }
191
+
192
+ c [src ].PathEnd = path .End (c [src ].ChainID ())
193
+ c [dst ].PathEnd = path .End (c [dst ].ChainID ())
194
+
195
+ // ensure that keys exist
196
+ if exists := c [src ].ChainProvider .KeyExists (c [src ].ChainProvider .Key ()); ! exists {
197
+ return fmt .Errorf ("key %s not found on chain %s \n " , c [src ].ChainProvider .Key (), c [src ].ChainID ())
198
+ }
199
+ if exists := c [dst ].ChainProvider .KeyExists (c [dst ].ChainProvider .Key ()); ! exists {
200
+ return fmt .Errorf ("key %s not found on chain %s \n " , c [dst ].ChainProvider .Key (), c [dst ].ChainID ())
201
+ }
202
+
203
+ // Query the latest heights on src and dst and retry if the query fails
204
+ var srch , dsth int64
205
+ if err = retry .Do (func () error {
206
+ srch , dsth , err = relayer .QueryLatestHeights (c [src ], c [dst ])
207
+ if srch == 0 || dsth == 0 || err != nil {
208
+ return fmt .Errorf ("failed to query latest heights. Err: %w" , err )
209
+ }
210
+ return err
211
+ }, relayer .RtyAtt , relayer .RtyDel , relayer .RtyErr ); err != nil {
212
+ return err
213
+ }
214
+
215
+ // Query the light signed headers for src & dst at the heights srch & dsth, retry if the query fails
216
+ var srcUpdateHeader , dstUpdateHeader exported.Header
217
+ if err = retry .Do (func () error {
218
+ srcUpdateHeader , dstUpdateHeader , err = relayer .GetLightSignedHeadersAtHeights (c [src ], c [dst ], srch , dsth )
219
+ if err != nil {
220
+ return fmt .Errorf ("failed to query light signed headers. Err: %w" , err )
221
+ }
222
+ return err
223
+ }, relayer .RtyAtt , relayer .RtyDel , relayer .RtyErr , retry .OnRetry (func (n uint , err error ) {
224
+ c [src ].LogRetryGetLightSignedHeader (n , err )
225
+ srch , dsth , _ = relayer .QueryLatestHeights (c [src ], c [dst ])
226
+ })); err != nil {
227
+ return err
228
+ }
229
+
230
+ modified , err := relayer .CreateClient (c [src ], c [dst ], srcUpdateHeader , dstUpdateHeader , allowUpdateAfterExpiry , allowUpdateAfterMisbehaviour , override )
231
+ if modified {
232
+ if err = overWriteConfig (config ); err != nil {
233
+ return err
234
+ }
235
+ }
236
+
237
+ return nil
238
+ },
239
+ }
240
+
241
+ return overrideFlag (clientParameterFlags (cmd ))
242
+ }
243
+
149
244
func updateClientsCmd () * cobra.Command {
150
245
cmd := & cobra.Command {
151
246
Use : "update-clients [path-name]" ,
@@ -407,7 +502,7 @@ $ %s tx connect demo-path`,
407
502
}
408
503
409
504
// create channel if it isn't already created
410
- modified , err = c [src ].CreateOpenChannels (c [dst ], 3 , to )
505
+ modified , err = c [src ].CreateOpenChannels (c [dst ], retries , to )
411
506
if modified {
412
507
if err := overWriteConfig (config ); err != nil {
413
508
return err
@@ -452,6 +547,49 @@ $ %s tx link-then-start demo-path --timeout 5s`, appName, appName)),
452
547
return overrideFlag (clientParameterFlags (strategyFlag (retryFlag (timeoutFlag (cmd )))))
453
548
}
454
549
550
+ func relayMsgCmd () * cobra.Command {
551
+ cmd := & cobra.Command {
552
+ Use : "relay-packet [path-name] [seq-num]" ,
553
+ Aliases : []string {"relay-pkt" },
554
+ Short : "relay a non-relayed packet with a specific sequence number, in both directions" ,
555
+ Args : cobra .ExactArgs (2 ),
556
+ Example : strings .TrimSpace (fmt .Sprintf (`
557
+ $ %s transact relay-packet demo-path 1
558
+ $ %s tx relay-pkt demo-path 1` ,
559
+ appName , appName ,
560
+ )),
561
+ RunE : func (cmd * cobra.Command , args []string ) error {
562
+ c , src , dst , err := config .ChainsFromPath (args [0 ])
563
+ if err != nil {
564
+ return err
565
+ }
566
+
567
+ if err = ensureKeysExist (c ); err != nil {
568
+ return err
569
+ }
570
+
571
+ maxTxSize , maxMsgLength , err := GetStartOptions (cmd )
572
+ if err != nil {
573
+ return err
574
+ }
575
+
576
+ seqNum , err := strconv .Atoi (args [1 ])
577
+ if err != nil {
578
+ return err
579
+ }
580
+
581
+ sp , err := relayer .UnrelayedSequences (c [src ], c [dst ])
582
+ if err != nil {
583
+ return err
584
+ }
585
+
586
+ return relayer .RelayPacket (c [src ], c [dst ], sp , maxTxSize , maxMsgLength , uint64 (seqNum ))
587
+ },
588
+ }
589
+
590
+ return strategyFlag (cmd )
591
+ }
592
+
455
593
func relayMsgsCmd () * cobra.Command {
456
594
cmd := & cobra.Command {
457
595
Use : "relay-packets [path-name]" ,
0 commit comments