layer_climb_core/signing/ibc/
handshake.rs

1use crate::{
2    events::{
3        EVENT_ATTR_IBC_CHANNEL_ID, EVENT_ATTR_IBC_CONNECTION_ID, EVENT_TYPE_IBC_CHANNEL_OPEN_INIT,
4        EVENT_TYPE_IBC_CHANNEL_OPEN_TRY, EVENT_TYPE_IBC_CONNECTION_OPEN_INIT,
5        EVENT_TYPE_IBC_CONNECTION_OPEN_TRY, EVENT_TYPE_IBC_CREATE_CLIENT,
6    },
7    ibc_types::{
8        IbcChannelId, IbcChannelOrdering, IbcChannelVersion, IbcClientId, IbcConnectionId,
9        IbcPortId,
10    },
11    prelude::*,
12};
13use anyhow::ensure;
14use serde::{Deserialize, Serialize};
15
16impl SigningClient {
17    pub async fn ibc_connection_handshake(
18        &self,
19        counterparty_client: &SigningClient,
20        client_id: Option<IbcClientId>,
21        counterparty_client_id: Option<IbcClientId>,
22        // if None, IbcConnectionHandshakeGasSimulationMultipliers::default() will be used
23        simulation_gas_multipliers: Option<IbcConnectionHandshakeGasSimulationMultipliers>,
24        logger: impl Fn(String),
25    ) -> Result<IbcConnectionHandshake> {
26        macro_rules! write_out {
27            ($($arg:tt)*) => {
28                logger(format!($($arg)*));
29            };
30        }
31        let client_id = match client_id {
32            Some(id) => id,
33            None => {
34                write_out!("No client ID for network 1, creating one");
35                let mut tx_builder = self.tx_builder();
36                if let Some(gas_multiplier) =
37                    simulation_gas_multipliers.as_ref().and_then(|m| m.client_1)
38                {
39                    tx_builder.set_gas_simulate_multiplier(gas_multiplier);
40                }
41                let tx_resp = self
42                    .ibc_create_client(&counterparty_client.querier, None, Some(tx_builder))
43                    .await?;
44                let events = CosmosTxEvents::from(&tx_resp);
45                let event = events
46                    .event_first_by_type(EVENT_TYPE_IBC_CREATE_CLIENT)
47                    .context("No create_client event found")?;
48                let attr = event
49                    .attributes()
50                    .find(|attr| attr.key() == "client_id")
51                    .context("No client_id attribute found")?;
52                let client_id = IbcClientId::new(attr.value().to_string());
53                write_out!("client ID for network 1 is {}", client_id);
54                client_id
55            }
56        };
57
58        let counterparty_client_id = match counterparty_client_id {
59            Some(id) => id,
60            None => {
61                write_out!("No client ID for network 2, creating one");
62                let mut tx_builder = counterparty_client.tx_builder();
63                if let Some(gas_multiplier) =
64                    simulation_gas_multipliers.as_ref().and_then(|m| m.client_2)
65                {
66                    tx_builder.set_gas_simulate_multiplier(gas_multiplier);
67                }
68                let tx_resp = counterparty_client
69                    .ibc_create_client(&self.querier, None, Some(tx_builder))
70                    .await?;
71                let events = CosmosTxEvents::from(&tx_resp);
72                let event = events
73                    .event_first_by_type(EVENT_TYPE_IBC_CREATE_CLIENT)
74                    .context("No create_client event found")?;
75                let attr = event
76                    .attributes()
77                    .find(|attr| attr.key() == "client_id")
78                    .context("No client_id attribute found")?;
79                let client_id = IbcClientId::new(attr.value().to_string());
80                write_out!("client ID for network 2 is {}", client_id);
81                client_id
82            }
83        };
84
85        // connection init
86        let connection_id = {
87            write_out!("[CONNECTION INIT] starting on chain {}", self.chain_id());
88            let mut tx_builder = self.tx_builder();
89            if let Some(gas_multiplier) = simulation_gas_multipliers
90                .as_ref()
91                .and_then(|m| m.connection_1)
92            {
93                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
94            }
95            let tx_resp = self
96                .ibc_open_connection_init(&client_id, &counterparty_client_id, Some(tx_builder))
97                .await?;
98            let events = CosmosTxEvents::from(&tx_resp);
99            // https://github.com/cosmos/ibc-go/blob/d771177acf66890c9c6f6e5df9a37b8031dbef7d/modules/core/03-connection/types/events.go#L19
100            let connection_id = events
101                .attr_first(
102                    EVENT_TYPE_IBC_CONNECTION_OPEN_INIT,
103                    EVENT_ATTR_IBC_CONNECTION_ID,
104                )?
105                .value()
106                .to_string();
107            let connection_id = IbcConnectionId::new(connection_id);
108            write_out!(
109                "[CONNECTION INIT] on chain {}, connection id: {}",
110                self.chain_id(),
111                connection_id
112            );
113            connection_id
114        };
115
116        // update clients
117        {
118            write_out!(
119                "[CLIENT UPDATE] starting {}:{} -> {}:{}",
120                self.chain_id(),
121                client_id,
122                counterparty_client.chain_id(),
123                counterparty_client_id
124            );
125            let mut tx_builder = self.tx_builder();
126            if let Some(gas_multiplier) = simulation_gas_multipliers
127                .as_ref()
128                .and_then(|m| m.update_client_1)
129            {
130                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
131            }
132            self.ibc_update_client(
133                &client_id,
134                &counterparty_client.querier,
135                None,
136                Some(tx_builder),
137            )
138            .await?;
139
140            write_out!(
141                "[CLIENT UPDATE] starting {}:{} -> {}:{}",
142                counterparty_client.chain_id(),
143                counterparty_client_id,
144                self.chain_id(),
145                client_id
146            );
147            let mut tx_builder = counterparty_client.tx_builder();
148            if let Some(gas_multiplier) = simulation_gas_multipliers
149                .as_ref()
150                .and_then(|m| m.update_client_2)
151            {
152                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
153            }
154            counterparty_client
155                .ibc_update_client(
156                    &counterparty_client_id,
157                    &self.querier,
158                    None,
159                    Some(tx_builder),
160                )
161                .await?;
162            write_out!("[CLIENTS UPDATED]");
163        }
164
165        // connection try
166        let counterparty_connection_id = {
167            write_out!(
168                "[CONNECTION TRY] starting on chain {}, connection_id: {}",
169                counterparty_client.chain_id(),
170                connection_id
171            );
172            let mut tx_builder = counterparty_client.tx_builder();
173            if let Some(gas_multiplier) = simulation_gas_multipliers
174                .as_ref()
175                .and_then(|m| m.connection_2)
176            {
177                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
178            }
179            let tx_resp = counterparty_client
180                .ibc_open_connection_try(
181                    &counterparty_client_id,
182                    &client_id,
183                    &connection_id,
184                    &self.querier,
185                    Some(tx_builder),
186                )
187                .await?;
188            let events = CosmosTxEvents::from(&tx_resp);
189            let counterparty_connection_id = events
190                .attr_first(
191                    EVENT_TYPE_IBC_CONNECTION_OPEN_TRY,
192                    EVENT_ATTR_IBC_CONNECTION_ID,
193                )?
194                .value()
195                .to_string();
196            let counterparty_connection_id = IbcConnectionId::new(counterparty_connection_id);
197            write_out!("[CONNECTION TRY] completed on chain {}, src connection_id: {}, dst connection_id: {}", counterparty_client.chain_id(), counterparty_connection_id, connection_id);
198            counterparty_connection_id
199        };
200
201        // update clients
202        {
203            write_out!(
204                "[CLIENT UPDATE] starting {}:{} -> {}:{}",
205                self.chain_id(),
206                client_id,
207                counterparty_client.chain_id(),
208                counterparty_client_id
209            );
210            let mut tx_builder = self.tx_builder();
211            if let Some(gas_multiplier) = simulation_gas_multipliers
212                .as_ref()
213                .and_then(|m| m.update_client_1)
214            {
215                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
216            }
217            self.ibc_update_client(
218                &client_id,
219                &counterparty_client.querier,
220                None,
221                Some(tx_builder),
222            )
223            .await?;
224
225            write_out!(
226                "[CLIENT UPDATE] starting {}:{} -> {}:{}",
227                counterparty_client.chain_id(),
228                counterparty_client_id,
229                self.chain_id(),
230                client_id
231            );
232            let mut tx_builder = counterparty_client.tx_builder();
233            if let Some(gas_multiplier) = simulation_gas_multipliers
234                .as_ref()
235                .and_then(|m| m.update_client_2)
236            {
237                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
238            }
239            counterparty_client
240                .ibc_update_client(
241                    &counterparty_client_id,
242                    &self.querier,
243                    None,
244                    Some(tx_builder),
245                )
246                .await?;
247            write_out!("[CLIENTS UPDATED]");
248        }
249
250        // connection ack
251        {
252            write_out!("[CONNECTION ACK] starting on chain {}, src connection_id: {}, dst connection_id: {}", self.chain_id(), connection_id, counterparty_connection_id);
253            let mut tx_builder = self.tx_builder();
254            if let Some(gas_multiplier) = simulation_gas_multipliers
255                .as_ref()
256                .and_then(|m| m.connection_1)
257            {
258                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
259            }
260            self.ibc_open_connection_ack(
261                &client_id,
262                &counterparty_client_id,
263                &connection_id,
264                &counterparty_connection_id,
265                &counterparty_client.querier,
266                Some(tx_builder),
267            )
268            .await?;
269            write_out!("[CONNECTION ACK] completed on chain {}, src connection_id: {}, dst connection_id: {}", self.chain_id(), connection_id, counterparty_connection_id);
270        };
271
272        // update clients
273        {
274            write_out!(
275                "[CLIENT UPDATE] starting {}:{} -> {}:{}",
276                self.chain_id(),
277                client_id,
278                counterparty_client.chain_id(),
279                counterparty_client_id
280            );
281            let mut tx_builder = self.tx_builder();
282            if let Some(gas_multiplier) = simulation_gas_multipliers
283                .as_ref()
284                .and_then(|m| m.update_client_1)
285            {
286                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
287            }
288            self.ibc_update_client(
289                &client_id,
290                &counterparty_client.querier,
291                None,
292                Some(tx_builder),
293            )
294            .await?;
295
296            write_out!(
297                "[CLIENT UPDATE] starting {}:{} -> {}:{}",
298                counterparty_client.chain_id(),
299                counterparty_client_id,
300                self.chain_id(),
301                client_id
302            );
303            let mut tx_builder = counterparty_client.tx_builder();
304            if let Some(gas_multiplier) = simulation_gas_multipliers
305                .as_ref()
306                .and_then(|m| m.update_client_2)
307            {
308                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
309            }
310            counterparty_client
311                .ibc_update_client(
312                    &counterparty_client_id,
313                    &self.querier,
314                    None,
315                    Some(tx_builder),
316                )
317                .await?;
318            write_out!("[CLIENTS UPDATED]");
319        }
320
321        // connection confirm
322        {
323            write_out!("[CONNECTION CONFIRM] starting on chain {}, src connection_id: {}, dst connection_id: {}", counterparty_client.chain_id(), counterparty_connection_id, connection_id);
324            let mut tx_builder = counterparty_client.tx_builder();
325            if let Some(gas_multiplier) = simulation_gas_multipliers
326                .as_ref()
327                .and_then(|m| m.connection_2)
328            {
329                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
330            }
331            counterparty_client
332                .ibc_open_connection_confirm(
333                    &counterparty_client_id,
334                    &client_id,
335                    &counterparty_connection_id,
336                    &connection_id,
337                    &self.querier,
338                    Some(tx_builder),
339                )
340                .await?;
341            write_out!("[CONNECTION CONFIRM] completed on chain {}, src connection_id: {}, dst connection_id: {}", counterparty_client.chain_id(), counterparty_connection_id, connection_id);
342        };
343
344        let connection = self.querier.ibc_connection(&connection_id, None).await?;
345        ensure!(
346            connection.state() == layer_climb_proto::ibc::connection::State::Open,
347            "connection state on {} is not {:?} instead it's {:?}",
348            self.querier.chain_config.chain_id,
349            layer_climb_proto::ibc::connection::State::Open,
350            connection.state()
351        );
352        let counterparty_connection = counterparty_client
353            .querier
354            .ibc_connection(&counterparty_connection_id, None)
355            .await?;
356        ensure!(
357            counterparty_connection.state() == layer_climb_proto::ibc::connection::State::Open,
358            "connection state on {} is not {:?} instead it's {:?}",
359            counterparty_client.querier.chain_config.chain_id,
360            layer_climb_proto::ibc::connection::State::Open,
361            counterparty_connection.state()
362        );
363
364        Ok(IbcConnectionHandshake {
365            client_id,
366            counterparty_client_id,
367            connection_id,
368            counterparty_connection_id,
369        })
370    }
371
372    #[allow(clippy::too_many_arguments)]
373    pub async fn ibc_channel_handshake(
374        &self,
375        counterparty_client: &SigningClient,
376        port_id: &IbcPortId,
377        counterparty_port_id: &IbcPortId,
378        version: &IbcChannelVersion,
379        ordering: IbcChannelOrdering,
380        conn_handshake: &IbcConnectionHandshake,
381        // if None, IbcChannelHandshakeGasSimulationMultipliers::default() will be used
382        simulation_gas_multipliers: Option<IbcChannelHandshakeGasSimulationMultipliers>,
383        logger: impl Fn(String),
384    ) -> Result<IbcChannelHandshake> {
385        macro_rules! write_out {
386            ($($arg:tt)*) => {
387                logger(format!($($arg)*));
388            };
389        }
390
391        let IbcConnectionHandshake {
392            client_id,
393            counterparty_client_id,
394            connection_id,
395            counterparty_connection_id,
396        } = conn_handshake;
397
398        // channel init
399        let channel_id = {
400            write_out!("[CHANNEL INIT] starting on chain {}", self.chain_id());
401
402            let mut tx_builder = self.tx_builder();
403            if let Some(gas_multiplier) = simulation_gas_multipliers
404                .as_ref()
405                .and_then(|m| m.channel_1)
406            {
407                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
408            }
409            let tx_resp = self
410                .ibc_open_channel_init(
411                    connection_id,
412                    port_id,
413                    version,
414                    ordering,
415                    counterparty_port_id,
416                    Some(tx_builder),
417                )
418                .await?;
419
420            let events = CosmosTxEvents::from(&tx_resp);
421            let channel_id = events
422                .attr_first(EVENT_TYPE_IBC_CHANNEL_OPEN_INIT, EVENT_ATTR_IBC_CHANNEL_ID)?
423                .value()
424                .to_string();
425            let channel_id = IbcChannelId::new(channel_id);
426            write_out!(
427                "[CHANNEL INIT] completed on chain {}, channel id: {}",
428                self.chain_id(),
429                channel_id
430            );
431            channel_id
432        };
433
434        // update clients
435        {
436            write_out!(
437                "[CLIENT UPDATE] starting {}:{} -> {}:{}",
438                self.chain_id(),
439                client_id,
440                counterparty_client.chain_id(),
441                counterparty_client_id
442            );
443            let mut tx_builder = self.tx_builder();
444            if let Some(gas_multiplier) = simulation_gas_multipliers
445                .as_ref()
446                .and_then(|m| m.update_client_1)
447            {
448                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
449            }
450            self.ibc_update_client(
451                client_id,
452                &counterparty_client.querier,
453                None,
454                Some(tx_builder),
455            )
456            .await?;
457
458            write_out!(
459                "[CLIENT UPDATE] starting {}:{} -> {}:{}",
460                counterparty_client.chain_id(),
461                counterparty_client_id,
462                self.chain_id(),
463                client_id
464            );
465            let mut tx_builder = counterparty_client.tx_builder();
466            if let Some(gas_multiplier) = simulation_gas_multipliers
467                .as_ref()
468                .and_then(|m| m.update_client_2)
469            {
470                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
471            }
472            counterparty_client
473                .ibc_update_client(
474                    counterparty_client_id,
475                    &self.querier,
476                    None,
477                    Some(tx_builder),
478                )
479                .await?;
480            write_out!("[CLIENTS UPDATED]");
481        }
482
483        let counterparty_channel_id = {
484            write_out!(
485                "[CHANNEL TRY] starting on chain {}, channel_id: {}",
486                counterparty_client.chain_id(),
487                channel_id
488            );
489
490            let mut tx_builder = counterparty_client.tx_builder();
491            if let Some(gas_multiplier) = simulation_gas_multipliers
492                .as_ref()
493                .and_then(|m| m.channel_2)
494            {
495                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
496            }
497            let tx_resp = counterparty_client
498                .ibc_open_channel_try(
499                    counterparty_client_id,
500                    counterparty_connection_id,
501                    counterparty_port_id,
502                    version,
503                    port_id,
504                    &channel_id,
505                    version,
506                    ordering,
507                    &self.querier,
508                    Some(tx_builder),
509                )
510                .await?;
511
512            let events = CosmosTxEvents::from(&tx_resp);
513            let counterparty_channel_id = events
514                .attr_first(EVENT_TYPE_IBC_CHANNEL_OPEN_TRY, EVENT_ATTR_IBC_CHANNEL_ID)?
515                .value()
516                .to_string();
517            let counterparty_channel_id = IbcChannelId::new(counterparty_channel_id);
518            write_out!(
519                "[CHANNEL TRY] completed on chain {}, src channel_id: {}, dest channel id: {}",
520                counterparty_client.chain_id(),
521                counterparty_channel_id,
522                channel_id
523            );
524            counterparty_channel_id
525        };
526
527        // update clients
528        {
529            write_out!(
530                "[CLIENT UPDATE] starting {}:{} -> {}:{}",
531                self.chain_id(),
532                client_id,
533                counterparty_client.chain_id(),
534                counterparty_client_id
535            );
536            let mut tx_builder = self.tx_builder();
537            if let Some(gas_multiplier) = simulation_gas_multipliers
538                .as_ref()
539                .and_then(|m| m.update_client_1)
540            {
541                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
542            }
543            self.ibc_update_client(
544                client_id,
545                &counterparty_client.querier,
546                None,
547                Some(tx_builder),
548            )
549            .await?;
550
551            write_out!(
552                "[CLIENT UPDATE] starting {}:{} -> {}:{}",
553                counterparty_client.chain_id(),
554                counterparty_client_id,
555                self.chain_id(),
556                client_id
557            );
558            let mut tx_builder = counterparty_client.tx_builder();
559            if let Some(gas_multiplier) = simulation_gas_multipliers
560                .as_ref()
561                .and_then(|m| m.update_client_2)
562            {
563                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
564            }
565            counterparty_client
566                .ibc_update_client(
567                    counterparty_client_id,
568                    &self.querier,
569                    None,
570                    Some(tx_builder),
571                )
572                .await?;
573            write_out!("[CLIENTS UPDATED]");
574        }
575
576        {
577            write_out!(
578                "[CHANNEL ACK] starting on chain {}, src channel_id: {}, dst channel_id: {}",
579                self.chain_id(),
580                channel_id,
581                counterparty_channel_id
582            );
583
584            let mut tx_builder = self.tx_builder();
585            if let Some(gas_multiplier) = simulation_gas_multipliers
586                .as_ref()
587                .and_then(|m| m.channel_1)
588            {
589                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
590            }
591            self.ibc_open_channel_ack(
592                client_id,
593                &channel_id,
594                port_id,
595                counterparty_port_id,
596                &counterparty_channel_id,
597                version,
598                &counterparty_client.querier,
599                Some(tx_builder),
600            )
601            .await?;
602            write_out!(
603                "[CHANNEL ACK] completed on chain {}, src channel_id: {}, dst channel_id: {}",
604                self.chain_id(),
605                channel_id,
606                counterparty_channel_id
607            );
608        };
609
610        // update clients
611        {
612            write_out!(
613                "[CLIENT UPDATE] starting {}:{} -> {}:{}",
614                self.chain_id(),
615                client_id,
616                counterparty_client.chain_id(),
617                counterparty_client_id
618            );
619            let mut tx_builder = self.tx_builder();
620            if let Some(gas_multiplier) = simulation_gas_multipliers
621                .as_ref()
622                .and_then(|m| m.update_client_1)
623            {
624                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
625            }
626            self.ibc_update_client(
627                client_id,
628                &counterparty_client.querier,
629                None,
630                Some(tx_builder),
631            )
632            .await?;
633
634            write_out!(
635                "[CLIENT UPDATE] starting {}:{} -> {}:{}",
636                counterparty_client.chain_id(),
637                counterparty_client_id,
638                self.chain_id(),
639                client_id
640            );
641            let mut tx_builder = counterparty_client.tx_builder();
642            if let Some(gas_multiplier) = simulation_gas_multipliers
643                .as_ref()
644                .and_then(|m| m.update_client_2)
645            {
646                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
647            }
648            counterparty_client
649                .ibc_update_client(
650                    counterparty_client_id,
651                    &self.querier,
652                    None,
653                    Some(tx_builder),
654                )
655                .await?;
656            write_out!("[CLIENTS UPDATED]");
657        }
658
659        {
660            write_out!(
661                "[CHANNEL CONFIRM] starting on chain {}, src channel_id: {}, dst channel_id: {}",
662                counterparty_client.chain_id(),
663                counterparty_channel_id,
664                channel_id
665            );
666
667            let mut tx_builder = counterparty_client.tx_builder();
668            if let Some(gas_multiplier) = simulation_gas_multipliers
669                .as_ref()
670                .and_then(|m| m.channel_2)
671            {
672                tx_builder.set_gas_simulate_multiplier(gas_multiplier);
673            }
674            counterparty_client
675                .ibc_open_channel_confirm(
676                    counterparty_client_id,
677                    &counterparty_channel_id,
678                    counterparty_port_id,
679                    port_id,
680                    &channel_id,
681                    &self.querier,
682                    Some(tx_builder),
683                )
684                .await?;
685
686            write_out!(
687                "[CHANNEL CONFIRM] completed on chain {}, src channel_id: {}, dst channel_id: {}",
688                counterparty_client.chain_id(),
689                counterparty_channel_id,
690                channel_id
691            );
692        };
693
694        let channel = self.querier.ibc_channel(&channel_id, port_id, None).await?;
695        ensure!(
696            channel.state() == layer_climb_proto::ibc::channel::State::Open,
697            "channel state on {} is not {:?} instead it's {:?}",
698            self.querier.chain_config.chain_id,
699            layer_climb_proto::ibc::channel::State::Open,
700            channel.state()
701        );
702        let counterparty_channel = counterparty_client
703            .querier
704            .ibc_channel(&counterparty_channel_id, counterparty_port_id, None)
705            .await?;
706        ensure!(
707            counterparty_channel.state() == layer_climb_proto::ibc::channel::State::Open,
708            "channel state on {} is not {:?} instead it's {:?}",
709            counterparty_client.querier.chain_config.chain_id,
710            layer_climb_proto::ibc::channel::State::Open,
711            counterparty_channel.state()
712        );
713
714        Ok(IbcChannelHandshake {
715            channel_id,
716            counterparty_channel_id,
717        })
718    }
719}
720
721#[derive(Debug, Clone, Serialize, Deserialize)]
722pub struct IbcConnectionHandshake {
723    pub client_id: IbcClientId,
724    pub counterparty_client_id: IbcClientId,
725    pub connection_id: IbcConnectionId,
726    pub counterparty_connection_id: IbcConnectionId,
727}
728
729#[derive(Debug, Clone, Serialize, Deserialize)]
730pub struct IbcChannelHandshake {
731    pub channel_id: IbcChannelId,
732    pub counterparty_channel_id: IbcChannelId,
733}
734
735#[derive(Serialize, Deserialize, Debug, Clone)]
736pub struct IbcConnectionHandshakeGasSimulationMultipliers {
737    pub client_1: Option<f32>,
738    pub client_2: Option<f32>,
739    pub connection_1: Option<f32>,
740    pub connection_2: Option<f32>,
741    pub update_client_1: Option<f32>,
742    pub update_client_2: Option<f32>,
743}
744
745impl Default for IbcConnectionHandshakeGasSimulationMultipliers {
746    fn default() -> Self {
747        Self {
748            client_1: Some(2.5),
749            client_2: Some(2.5),
750            connection_1: Some(2.5),
751            connection_2: Some(2.5),
752            update_client_1: Some(2.5),
753            update_client_2: Some(2.5),
754        }
755    }
756}
757
758#[derive(Serialize, Deserialize, Debug, Clone)]
759pub struct IbcChannelHandshakeGasSimulationMultipliers {
760    pub channel_1: Option<f32>,
761    pub channel_2: Option<f32>,
762    pub update_client_1: Option<f32>,
763    pub update_client_2: Option<f32>,
764}
765
766impl Default for IbcChannelHandshakeGasSimulationMultipliers {
767    fn default() -> Self {
768        Self {
769            channel_1: Some(2.5),
770            channel_2: Some(2.5),
771            update_client_1: Some(2.5),
772            update_client_2: Some(2.5),
773        }
774    }
775}