penumbra_sdk_ibc/component/
connection.rs1use anyhow::Result;
2use async_trait::async_trait;
3use cnidarium::{StateRead, StateWrite};
4use ibc_types::{
5 core::{
6 client::ClientId,
7 connection::ConnectionId,
8 connection::{ClientPaths, ConnectionEnd},
9 },
10 path::{ClientConnectionPath, ConnectionPath},
11};
12use penumbra_sdk_proto::{StateReadProto, StateWriteProto};
13
14use crate::{prefix::MerklePrefixExt, IBC_COMMITMENT_PREFIX};
15
16use super::{connection_counter::ConnectionCounter, state_key};
17
18#[async_trait]
19pub trait StateWriteExt: StateWrite {
20 fn put_connection_counter(&mut self, counter: ConnectionCounter) {
21 self.put(state_key::counter().into(), counter);
22 }
23 fn put_client_connection(&mut self, client_id: &ClientId, paths: ClientPaths) {
24 self.put(
25 IBC_COMMITMENT_PREFIX.apply_string(ClientConnectionPath::new(client_id).to_string()),
26 paths.clone(),
27 );
28 }
29
30 async fn put_new_connection(
33 &mut self,
34 connection_id: &ConnectionId,
35 connection: ConnectionEnd,
36 ) -> Result<()> {
37 self.put(
38 IBC_COMMITMENT_PREFIX.apply_string(ConnectionPath::new(connection_id).to_string()),
39 connection.clone(),
40 );
41
42 let mut client_paths = self.get_client_connections(&connection.client_id).await?;
43 client_paths.paths.push(connection_id.clone());
44 self.put_client_connection(&connection.client_id, client_paths);
45
46 let counter = self
47 .get_connection_counter()
48 .await
49 .unwrap_or(ConnectionCounter(0));
50 self.put_connection_counter(ConnectionCounter(counter.0 + 1));
51
52 return Ok(());
53 }
54
55 fn update_connection(&mut self, connection_id: &ConnectionId, connection: ConnectionEnd) {
56 self.put(
57 IBC_COMMITMENT_PREFIX.apply_string(ConnectionPath::new(connection_id).to_string()),
58 connection.clone(),
59 );
60 }
61}
62
63impl<T: StateWrite + ?Sized> StateWriteExt for T {}
64
65#[async_trait]
66pub trait StateReadExt: StateRead {
67 async fn get_connection_counter(&self) -> Result<ConnectionCounter> {
68 self.get(state_key::counter())
69 .await
70 .map(|counter| counter.unwrap_or(ConnectionCounter(0)))
71 }
72
73 async fn get_connection(&self, connection_id: &ConnectionId) -> Result<Option<ConnectionEnd>> {
74 self.get(
75 &IBC_COMMITMENT_PREFIX.apply_string(ConnectionPath::new(connection_id).to_string()),
76 )
77 .await
78 }
79
80 async fn get_client_connections(&self, client_id: &ClientId) -> Result<ClientPaths> {
81 self.get(
82 &IBC_COMMITMENT_PREFIX.apply_string(ClientConnectionPath::new(client_id).to_string()),
83 )
84 .await
85 .map(|paths| paths.unwrap_or(ClientPaths { paths: vec![] }))
86 }
87}
88
89impl<T: StateRead + ?Sized> StateReadExt for T {}