|
13 | 13 | // limitations under the License. |
14 | 14 |
|
15 | 15 | use crate::{ |
16 | | - chain::{AnyConfig, Config, CoreConfig}, |
| 16 | + chain::{AnyChain, AnyConfig, Config, CoreConfig}, |
17 | 17 | fish, relay, Mode, |
18 | 18 | }; |
19 | 19 | use anyhow::{anyhow, Result}; |
20 | 20 | use clap::{Args, Parser}; |
21 | | -use ibc::core::{ics04_channel::channel::Order, ics24_host::identifier::PortId}; |
| 21 | +use ibc::core::{ |
| 22 | + ics04_channel::channel::{ChannelEnd, Order}, |
| 23 | + ics24_host::identifier::PortId, |
| 24 | +}; |
22 | 25 | use metrics::{data::Metrics, handler::MetricsHandler, init_prometheus}; |
23 | 26 | use primitives::{ |
| 27 | + error::Error, |
24 | 28 | utils::{create_channel, create_clients, create_connection}, |
25 | 29 | Chain, IbcProvider, |
26 | 30 | }; |
@@ -52,9 +56,9 @@ pub enum Subcommand { |
52 | 56 | #[clap(name = "create-channel", about = "Creates a channel on the specified port")] |
53 | 57 | CreateChannel(Cmd), |
54 | 58 | #[clap(name = "query", about = "Query commands")] |
55 | | - Client { |
| 59 | + Query { |
56 | 60 | #[command(subcommand)] |
57 | | - client: QueryCmd, |
| 61 | + query: QueryCmd, |
58 | 62 | #[command(flatten)] |
59 | 63 | cmd: Cmd, |
60 | 64 | }, |
@@ -126,7 +130,7 @@ impl UploadWasmCmd { |
126 | 130 | } |
127 | 131 |
|
128 | 132 | impl Cmd { |
129 | | - async fn parse_config(&self) -> Result<Config> { |
| 133 | + pub async fn parse_config(&self) -> Result<Config> { |
130 | 134 | use tokio::fs::read_to_string; |
131 | 135 | let path_a: PathBuf = self.config_a.parse()?; |
132 | 136 | let path_b: PathBuf = self.config_b.parse()?; |
@@ -289,12 +293,124 @@ pub enum QueryCmd { |
289 | 293 | Packets(QueryPacketsCmd), |
290 | 294 | } |
291 | 295 |
|
| 296 | +impl QueryCmd { |
| 297 | + pub async fn run(&self, config: Config) -> anyhow::Result<()> { |
| 298 | + let chain_a = config.chain_a.into_client().await?; |
| 299 | + let chain_b = config.chain_b.into_client().await?; |
| 300 | + |
| 301 | + match self { |
| 302 | + QueryCmd::Packets(query) => query.run(chain_a, chain_b).await, |
| 303 | + } |
| 304 | + } |
| 305 | +} |
| 306 | + |
292 | 307 | #[derive(Debug, Clone, clap::Subcommand)] |
293 | 308 | pub enum QueryPacketsCmd { |
294 | 309 | /// Trace packets |
295 | 310 | Trace(TracePacketsCmd), |
296 | 311 | } |
297 | 312 |
|
| 313 | +impl QueryPacketsCmd { |
| 314 | + pub(crate) async fn run(&self, chain_a: AnyChain, chain_b: AnyChain) -> anyhow::Result<()> { |
| 315 | + let name_a = chain_a.name(); |
| 316 | + let name_b = chain_b.name(); |
| 317 | + let (height_a, _) = chain_a.latest_height_and_timestamp().await?; |
| 318 | + let (_height_b, _) = chain_b.latest_height_and_timestamp().await?; |
| 319 | + |
| 320 | + match self { |
| 321 | + QueryPacketsCmd::Trace(cmd) => { |
| 322 | + let sequence = cmd.sequence; |
| 323 | + let set = chain_a.channel_whitelist(); |
| 324 | + if set.is_empty() { |
| 325 | + println!("No channels found on {name_a}"); |
| 326 | + return Ok(()) |
| 327 | + } |
| 328 | + for (channel_id, port_id) in set { |
| 329 | + let channel_response = |
| 330 | + chain_a.query_channel_end(height_a, channel_id, port_id.clone()).await?; |
| 331 | + let channel_end = |
| 332 | + ChannelEnd::try_from(channel_response.channel.ok_or_else(|| { |
| 333 | + Error::Custom("ChannelEnd not could not be decoded".to_string()) |
| 334 | + })?) |
| 335 | + .map_err(|e| Error::Custom(e.to_string()))?; |
| 336 | + let counterparty_channel_id = |
| 337 | + channel_end.counterparty().channel_id.ok_or_else(|| { |
| 338 | + Error::Custom("Expected counterparty channel id".to_string()) |
| 339 | + })?; |
| 340 | + let counterparty_port_id = channel_end.counterparty().port_id.clone(); |
| 341 | + |
| 342 | + let maybe_received = chain_b |
| 343 | + .query_received_packets( |
| 344 | + counterparty_channel_id.clone(), |
| 345 | + counterparty_port_id.clone(), |
| 346 | + vec![sequence], |
| 347 | + ) |
| 348 | + .await? |
| 349 | + .pop(); |
| 350 | + |
| 351 | + if let Some(received) = maybe_received { |
| 352 | + println!("Packet {sequence} was received on {name_b}: {received}"); |
| 353 | + let unreceived_acks = chain_a |
| 354 | + .query_unreceived_acknowledgements( |
| 355 | + height_a, |
| 356 | + channel_id.clone(), |
| 357 | + port_id.clone(), |
| 358 | + vec![sequence], |
| 359 | + ) |
| 360 | + .await?; |
| 361 | + if unreceived_acks.is_empty() { |
| 362 | + println!("Packet {sequence} was acknowledged on {name_b}"); |
| 363 | + } else { |
| 364 | + println!("Packet {sequence} was not acknowledged on {name_b}"); |
| 365 | + } |
| 366 | + continue; |
| 367 | + } |
| 368 | + let sent_packets = chain_a |
| 369 | + .query_send_packets(channel_id.clone(), port_id.clone(), vec![sequence]) |
| 370 | + .await?; |
| 371 | + if sent_packets.is_empty() { |
| 372 | + println!("Packet {sequence} not found"); |
| 373 | + continue; |
| 374 | + } |
| 375 | + for packet_info in sent_packets { |
| 376 | + let seq = packet_info.sequence; |
| 377 | + println!("Sent packet {} ({name_a}->{name_b}): {}", seq, packet_info); |
| 378 | + let received = chain_b |
| 379 | + .query_received_packets( |
| 380 | + packet_info.destination_channel.parse()?, |
| 381 | + packet_info.destination_port.parse()?, |
| 382 | + vec![seq], |
| 383 | + ) |
| 384 | + .await? |
| 385 | + .pop(); |
| 386 | + if received.is_none() { |
| 387 | + println!("Packet {seq} ({name_a}->{name_b}) was not received"); |
| 388 | + continue; |
| 389 | + } |
| 390 | + |
| 391 | + println!("Received packet {seq} ({name_a}->{name_b}) {received:?}"); |
| 392 | + |
| 393 | + let ack = chain_a |
| 394 | + .query_unreceived_acknowledgements( |
| 395 | + height_a, |
| 396 | + channel_id.clone(), |
| 397 | + port_id.clone(), |
| 398 | + vec![seq], |
| 399 | + ) |
| 400 | + .await?; |
| 401 | + if ack.is_empty() { |
| 402 | + println!("Packet {seq} ({name_a}->{name_b}) was acknowledged"); |
| 403 | + } else { |
| 404 | + println!("Packet {seq} ({name_a}->{name_b}) was not acknowledged"); |
| 405 | + } |
| 406 | + } |
| 407 | + } |
| 408 | + Ok(()) |
| 409 | + }, |
| 410 | + } |
| 411 | + } |
| 412 | +} |
| 413 | + |
298 | 414 | #[derive(Debug, Clone, Args)] |
299 | 415 | pub struct TracePacketsCmd { |
300 | 416 | pub sequence: u64, |
|
0 commit comments