#![no_std]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
extern crate alloc;
#[cfg(any(test, feature = "std"))]
extern crate std;
mod prelude;
use crate::prelude::*;
use ibc_types_core_client::Height;
use core::str::FromStr;
use ibc_types_core_channel::{packet::Sequence, ChannelId, PortId};
use ibc_types_core_client::ClientId;
use ibc_types_core_connection::ConnectionId;
use derive_more::{Display, From};
pub const IBC_QUERY_PATH: &str = "store/ibc/key";
pub const SDK_UPGRADE_QUERY_PATH: &str = "store/upgrade/key";
const UPGRADED_IBC_STATE: &str = "upgradedIBCState";
const UPGRADED_CLIENT_STATE: &str = "upgradedClient";
const UPGRADED_CLIENT_CONSENSUS_STATE: &str = "upgradedConsState";
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, From, Display)]
pub enum Path {
ClientType(ClientTypePath),
ClientState(ClientStatePath),
ClientConsensusState(ClientConsensusStatePath),
ClientConnection(ClientConnectionPath),
Connection(ConnectionPath),
Ports(PortPath),
ChannelEnd(ChannelEndPath),
SeqSend(SeqSendPath),
SeqRecv(SeqRecvPath),
SeqAck(SeqAckPath),
Commitment(CommitmentPath),
Ack(AckPath),
Receipt(ReceiptPath),
Upgrade(ClientUpgradePath),
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
#[display(fmt = "clients/{_0}/clientType")]
pub struct ClientTypePath(pub ClientId);
impl ClientTypePath {
pub fn new(client_id: &ClientId) -> ClientTypePath {
ClientTypePath(client_id.clone())
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
#[display(fmt = "clients/{_0}/clientState")]
pub struct ClientStatePath(pub ClientId);
impl ClientStatePath {
pub fn new(client_id: &ClientId) -> ClientStatePath {
ClientStatePath(client_id.clone())
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
#[display(fmt = "clients/{client_id}/consensusStates/{epoch}-{height}")]
pub struct ClientConsensusStatePath {
pub client_id: ClientId,
pub epoch: u64,
pub height: u64,
}
impl ClientConsensusStatePath {
pub fn new(client_id: &ClientId, height: &Height) -> ClientConsensusStatePath {
ClientConsensusStatePath {
client_id: client_id.clone(),
epoch: height.revision_number(),
height: height.revision_height(),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
#[display(fmt = "clients/{_0}/connections")]
pub struct ClientConnectionPath(pub ClientId);
impl ClientConnectionPath {
pub fn new(client_id: &ClientId) -> ClientConnectionPath {
ClientConnectionPath(client_id.clone())
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
#[display(fmt = "connections/{_0}")]
pub struct ConnectionPath(pub ConnectionId);
impl ConnectionPath {
pub fn new(connection_id: &ConnectionId) -> ConnectionPath {
ConnectionPath(connection_id.clone())
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
#[display(fmt = "ports/{_0}")]
pub struct PortPath(pub PortId);
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
#[display(fmt = "channelEnds/ports/{_0}/channels/{_1}")]
pub struct ChannelEndPath(pub PortId, pub ChannelId);
impl ChannelEndPath {
pub fn new(port_id: &PortId, channel_id: &ChannelId) -> ChannelEndPath {
ChannelEndPath(port_id.clone(), channel_id.clone())
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
#[display(fmt = "nextSequenceSend/ports/{_0}/channels/{_1}")]
pub struct SeqSendPath(pub PortId, pub ChannelId);
impl SeqSendPath {
pub fn new(port_id: &PortId, channel_id: &ChannelId) -> SeqSendPath {
SeqSendPath(port_id.clone(), channel_id.clone())
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
#[display(fmt = "nextSequenceRecv/ports/{_0}/channels/{_1}")]
pub struct SeqRecvPath(pub PortId, pub ChannelId);
impl SeqRecvPath {
pub fn new(port_id: &PortId, channel_id: &ChannelId) -> SeqRecvPath {
SeqRecvPath(port_id.clone(), channel_id.clone())
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
#[display(fmt = "nextSequenceAck/ports/{_0}/channels/{_1}")]
pub struct SeqAckPath(pub PortId, pub ChannelId);
impl SeqAckPath {
pub fn new(port_id: &PortId, channel_id: &ChannelId) -> SeqAckPath {
SeqAckPath(port_id.clone(), channel_id.clone())
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
#[display(fmt = "commitments/ports/{port_id}/channels/{channel_id}/sequences/{sequence}")]
pub struct CommitmentPath {
pub port_id: PortId,
pub channel_id: ChannelId,
pub sequence: Sequence,
}
impl CommitmentPath {
pub fn new(port_id: &PortId, channel_id: &ChannelId, sequence: Sequence) -> CommitmentPath {
CommitmentPath {
port_id: port_id.clone(),
channel_id: channel_id.clone(),
sequence,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
#[display(fmt = "acks/ports/{port_id}/channels/{channel_id}/sequences/{sequence}")]
pub struct AckPath {
pub port_id: PortId,
pub channel_id: ChannelId,
pub sequence: Sequence,
}
impl AckPath {
pub fn new(port_id: &PortId, channel_id: &ChannelId, sequence: Sequence) -> AckPath {
AckPath {
port_id: port_id.clone(),
channel_id: channel_id.clone(),
sequence,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
#[display(fmt = "receipts/ports/{port_id}/channels/{channel_id}/sequences/{sequence}")]
pub struct ReceiptPath {
pub port_id: PortId,
pub channel_id: ChannelId,
pub sequence: Sequence,
}
impl ReceiptPath {
pub fn new(port_id: &PortId, channel_id: &ChannelId, sequence: Sequence) -> ReceiptPath {
ReceiptPath {
port_id: port_id.clone(),
channel_id: channel_id.clone(),
sequence,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
pub enum ClientUpgradePath {
#[display(fmt = "{UPGRADED_IBC_STATE}/{_0}/{UPGRADED_CLIENT_STATE}")]
UpgradedClientState(u64),
#[display(fmt = "{UPGRADED_IBC_STATE}/{_0}/{UPGRADED_CLIENT_CONSENSUS_STATE}")]
UpgradedClientConsensusState(u64),
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
enum SubPath {
Channels(ChannelId),
Sequences(Sequence),
}
impl Path {
pub fn is_provable(&self) -> bool {
!matches!(&self, Path::ClientConnection(_) | Path::Ports(_))
}
pub fn into_bytes(self) -> Vec<u8> {
self.to_string().into_bytes()
}
}
#[derive(Debug, displaydoc::Display)]
pub enum PathError {
ParseFailure { path: String },
}
#[cfg(feature = "std")]
impl std::error::Error for PathError {}
impl FromStr for Path {
type Err = PathError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let components: Vec<&str> = s.split('/').collect();
parse_client_paths(&components)
.or_else(|| parse_connections(&components))
.or_else(|| parse_ports(&components))
.or_else(|| parse_channel_ends(&components))
.or_else(|| parse_seqs(&components))
.or_else(|| parse_commitments(&components))
.or_else(|| parse_acks(&components))
.or_else(|| parse_receipts(&components))
.or_else(|| parse_upgrades(&components))
.ok_or(PathError::ParseFailure {
path: s.to_string(),
})
}
}
fn parse_client_paths(components: &[&str]) -> Option<Path> {
let first = match components.first() {
Some(f) => *f,
None => return None,
};
if first != "clients" {
return None;
}
let client_id = match ClientId::from_str(components[1]) {
Ok(s) => s,
Err(_) => return None,
};
if components.len() == 3 {
match components[2] {
"clientType" => Some(ClientTypePath(client_id).into()),
"clientState" => Some(ClientStatePath(client_id).into()),
"connections" => Some(ClientConnectionPath(client_id).into()),
_ => None,
}
} else if components.len() == 4 {
if "consensusStates" != components[2] {
return None;
}
let epoch_height = match components.last() {
Some(eh) => *eh,
None => return None,
};
let epoch_height: Vec<&str> = epoch_height.split('-').collect();
if epoch_height.len() != 2 {
return None;
}
let epoch = epoch_height[0];
let height = epoch_height[1];
let epoch = match epoch.parse::<u64>() {
Ok(ep) => ep,
Err(_) => return None,
};
let height = match height.parse::<u64>() {
Ok(h) => h,
Err(_) => return None,
};
Some(
ClientConsensusStatePath {
client_id,
epoch,
height,
}
.into(),
)
} else {
None
}
}
fn parse_connections(components: &[&str]) -> Option<Path> {
if components.len() != 2 {
return None;
}
let first = match components.first() {
Some(f) => *f,
None => return None,
};
if first != "connections" {
return None;
}
let connection_id = match components.last() {
Some(c) => *c,
None => return None,
};
let connection_id = match ConnectionId::from_str(connection_id) {
Ok(c) => c,
Err(_) => return None,
};
Some(ConnectionPath(connection_id).into())
}
fn parse_ports(components: &[&str]) -> Option<Path> {
if components.len() != 2 {
return None;
}
let first = match components.first() {
Some(f) => *f,
None => return None,
};
if first != "ports" {
return None;
}
let port_id = match components.last() {
Some(p) => *p,
None => return None,
};
let port_id = match PortId::from_str(port_id) {
Ok(p) => p,
Err(_) => return None,
};
Some(PortPath(port_id).into())
}
fn parse_channels(components: &[&str]) -> Option<SubPath> {
if components.len() != 2 {
return None;
}
let first = match components.first() {
Some(f) => *f,
None => return None,
};
if first != "channels" {
return None;
}
let channel_id = match components.last() {
Some(c) => *c,
None => return None,
};
let channel_id = match ChannelId::from_str(channel_id) {
Ok(c) => c,
Err(_) => return None,
};
Some(SubPath::Channels(channel_id))
}
fn parse_sequences(components: &[&str]) -> Option<SubPath> {
if components.len() != 2 {
return None;
}
let first = match components.first() {
Some(f) => *f,
None => return None,
};
if first != "sequences" {
return None;
}
let sequence_number = match components.last() {
Some(s) => *s,
None => return None,
};
match Sequence::from_str(sequence_number) {
Ok(seq) => Some(SubPath::Sequences(seq)),
Err(_) => None,
}
}
fn parse_channel_ends(components: &[&str]) -> Option<Path> {
if components.len() != 5 {
return None;
}
let first = match components.first() {
Some(f) => *f,
None => return None,
};
if first != "channelEnds" {
return None;
}
let port = parse_ports(&components[1..=2]);
let channel = parse_channels(&components[3..=4]);
let port_id = if let Some(Path::Ports(PortPath(port_id))) = port {
port_id
} else {
return None;
};
let channel_id = if let Some(SubPath::Channels(channel_id)) = channel {
channel_id
} else {
return None;
};
Some(ChannelEndPath(port_id, channel_id).into())
}
fn parse_seqs(components: &[&str]) -> Option<Path> {
if components.len() != 5 {
return None;
}
let first = match components.first() {
Some(f) => *f,
None => return None,
};
let port = parse_ports(&components[1..=2]);
let channel = parse_channels(&components[3..=4]);
let port_id = if let Some(Path::Ports(PortPath(port_id))) = port {
port_id
} else {
return None;
};
let channel_id = if let Some(SubPath::Channels(channel_id)) = channel {
channel_id
} else {
return None;
};
match first {
"nextSequenceSend" => Some(SeqSendPath(port_id, channel_id).into()),
"nextSequenceRecv" => Some(SeqRecvPath(port_id, channel_id).into()),
"nextSequenceAck" => Some(SeqAckPath(port_id, channel_id).into()),
_ => None,
}
}
fn parse_commitments(components: &[&str]) -> Option<Path> {
if components.len() != 7 {
return None;
}
let first = match components.first() {
Some(f) => *f,
None => return None,
};
if first != "commitments" {
return None;
}
let port = parse_ports(&components[1..=2]);
let channel = parse_channels(&components[3..=4]);
let sequence = parse_sequences(&components[5..]);
let port_id = if let Some(Path::Ports(PortPath(port_id))) = port {
port_id
} else {
return None;
};
let channel_id = if let Some(SubPath::Channels(channel_id)) = channel {
channel_id
} else {
return None;
};
let sequence = if let Some(SubPath::Sequences(seq)) = sequence {
seq
} else {
return None;
};
Some(
CommitmentPath {
port_id,
channel_id,
sequence,
}
.into(),
)
}
fn parse_acks(components: &[&str]) -> Option<Path> {
if components.len() != 7 {
return None;
}
let first = match components.first() {
Some(f) => *f,
None => return None,
};
if first != "acks" {
return None;
}
let port = parse_ports(&components[1..=2]);
let channel = parse_channels(&components[3..=4]);
let sequence = parse_sequences(&components[5..]);
let port_id = if let Some(Path::Ports(PortPath(port_id))) = port {
port_id
} else {
return None;
};
let channel_id = if let Some(SubPath::Channels(channel_id)) = channel {
channel_id
} else {
return None;
};
let sequence = if let Some(SubPath::Sequences(seq)) = sequence {
seq
} else {
return None;
};
Some(
AckPath {
port_id,
channel_id,
sequence,
}
.into(),
)
}
fn parse_receipts(components: &[&str]) -> Option<Path> {
if components.len() != 7 {
return None;
}
let first = match components.first() {
Some(f) => *f,
None => return None,
};
if first != "receipts" {
return None;
}
let port = parse_ports(&components[1..=2]);
let channel = parse_channels(&components[3..=4]);
let sequence = parse_sequences(&components[5..]);
let port_id = if let Some(Path::Ports(PortPath(port_id))) = port {
port_id
} else {
return None;
};
let channel_id = if let Some(SubPath::Channels(channel_id)) = channel {
channel_id
} else {
return None;
};
let sequence = if let Some(SubPath::Sequences(seq)) = sequence {
seq
} else {
return None;
};
Some(
ReceiptPath {
port_id,
channel_id,
sequence,
}
.into(),
)
}
fn parse_upgrades(components: &[&str]) -> Option<Path> {
if components.len() != 3 {
return None;
}
let first = match components.first() {
Some(f) => *f,
None => return None,
};
if first != UPGRADED_IBC_STATE {
return None;
}
let last = match components.last() {
Some(l) => *l,
None => return None,
};
let height = match components[1].parse::<u64>() {
Ok(h) => h,
Err(_) => return None,
};
match last {
UPGRADED_CLIENT_STATE => Some(ClientUpgradePath::UpgradedClientState(height).into()),
UPGRADED_CLIENT_CONSENSUS_STATE => {
Some(ClientUpgradePath::UpgradedClientConsensusState(height).into())
}
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
use core::str::FromStr;
#[test]
fn invalid_path_doesnt_parse() {
let invalid_path = Path::from_str("clients/clientType");
assert!(invalid_path.is_err());
}
#[test]
fn test_parse_client_paths_fn() {
let path = "clients/07-tendermint-0/clientType";
let components: Vec<&str> = path.split('/').collect();
assert_eq!(
parse_client_paths(&components),
Some(Path::ClientType(ClientTypePath(ClientId::default())))
);
let path = "clients/07-tendermint-0/clientState";
let components: Vec<&str> = path.split('/').collect();
assert_eq!(
parse_client_paths(&components),
Some(Path::ClientState(ClientStatePath(ClientId::default())))
);
let path = "clients/07-tendermint-0/consensusStates/15-31";
let components: Vec<&str> = path.split('/').collect();
assert_eq!(
parse_client_paths(&components),
Some(Path::ClientConsensusState(ClientConsensusStatePath {
client_id: ClientId::default(),
epoch: 15,
height: 31,
}))
);
}
#[test]
fn client_type_path_parses() {
let path = "clients/07-tendermint-0/clientType";
let path = Path::from_str(path);
assert!(path.is_ok());
assert_eq!(
path.unwrap(),
Path::ClientType(ClientTypePath(ClientId::default()))
);
}
#[test]
fn client_state_path_parses() {
let path = "clients/07-tendermint-0/clientState";
let path = Path::from_str(path);
assert!(path.is_ok());
assert_eq!(
path.unwrap(),
Path::ClientState(ClientStatePath(ClientId::default()))
);
}
#[test]
fn client_consensus_state_path_parses() {
let path = "clients/07-tendermint-0/consensusStates/15-31";
let path = Path::from_str(path);
assert!(path.is_ok());
assert_eq!(
path.unwrap(),
Path::ClientConsensusState(ClientConsensusStatePath {
client_id: ClientId::default(),
epoch: 15,
height: 31,
})
);
}
#[test]
fn client_connections_path_parses() {
let path = "clients/07-tendermint-0/connections";
let path = Path::from_str(path);
assert!(path.is_ok());
assert_eq!(
path.unwrap(),
Path::ClientConnection(ClientConnectionPath(ClientId::default()))
);
}
#[test]
fn test_parse_connections_fn() {
let path = "connections/connection-0";
let components: Vec<&str> = path.split('/').collect();
assert_eq!(
parse_connections(&components),
Some(Path::Connection(ConnectionPath(ConnectionId::new(0)))),
);
}
#[test]
fn connections_path_parses() {
let path = "connections/connection-0";
let path = Path::from_str(path);
assert!(path.is_ok());
assert_eq!(
path.unwrap(),
Path::Connection(ConnectionPath(ConnectionId::new(0)))
);
}
#[test]
fn test_parse_ports_fn() {
let path = "ports/defaultPort";
let components: Vec<&str> = path.split('/').collect();
assert_eq!(
parse_ports(&components),
Some(Path::Ports(PortPath(PortId::default()))),
);
}
#[test]
fn ports_path_parses() {
let path = "ports/defaultPort";
let path = Path::from_str(path);
assert!(path.is_ok());
assert_eq!(path.unwrap(), Path::Ports(PortPath(PortId::default())));
}
#[test]
fn test_parse_channels_fn() {
let path = "channels/channel-0";
let components: Vec<&str> = path.split('/').collect();
assert_eq!(
parse_channels(&components),
Some(SubPath::Channels(ChannelId::default())),
);
}
#[test]
fn channels_path_doesnt_parse() {
let path = "channels/channel-0";
let path = Path::from_str(path);
assert!(path.is_err());
}
#[test]
fn test_parse_sequences_fn() {
let path = "sequences/0";
let components: Vec<&str> = path.split('/').collect();
assert_eq!(
parse_sequences(&components),
Some(SubPath::Sequences(Sequence::default()))
);
}
#[test]
fn sequences_path_doesnt_parse() {
let path = "sequences/0";
let path = Path::from_str(path);
assert!(path.is_err());
}
#[test]
fn test_parse_channel_ends_fn() {
let path = "channelEnds/ports/defaultPort/channels/channel-0";
let components: Vec<&str> = path.split('/').collect();
assert_eq!(
parse_channel_ends(&components),
Some(Path::ChannelEnd(ChannelEndPath(
PortId::default(),
ChannelId::default()
))),
);
}
#[test]
fn channel_ends_path_parses() {
let path = "channelEnds/ports/defaultPort/channels/channel-0";
let path = Path::from_str(path);
assert!(path.is_ok());
assert_eq!(
path.unwrap(),
Path::ChannelEnd(ChannelEndPath(PortId::default(), ChannelId::default())),
);
}
#[test]
fn test_parse_seqs_fn() {
let path = "nextSequenceSend/ports/defaultPort/channels/channel-0";
let components: Vec<&str> = path.split('/').collect();
assert_eq!(
parse_seqs(&components),
Some(Path::SeqSend(SeqSendPath(
PortId::default(),
ChannelId::default()
))),
);
let path = "nextSequenceRecv/ports/defaultPort/channels/channel-0";
let components: Vec<&str> = path.split('/').collect();
assert_eq!(
parse_seqs(&components),
Some(Path::SeqRecv(SeqRecvPath(
PortId::default(),
ChannelId::default()
))),
);
let path = "nextSequenceAck/ports/defaultPort/channels/channel-0";
let components: Vec<&str> = path.split('/').collect();
assert_eq!(
parse_seqs(&components),
Some(Path::SeqAck(SeqAckPath(
PortId::default(),
ChannelId::default()
))),
);
}
#[test]
fn sequence_send_path_parses() {
let path = "nextSequenceSend/ports/defaultPort/channels/channel-0";
let path = Path::from_str(path);
assert!(path.is_ok());
assert_eq!(
path.unwrap(),
Path::SeqSend(SeqSendPath(PortId::default(), ChannelId::default())),
);
}
#[test]
fn sequence_recv_path_parses() {
let path = "nextSequenceRecv/ports/defaultPort/channels/channel-0";
let path = Path::from_str(path);
assert!(path.is_ok());
assert_eq!(
path.unwrap(),
Path::SeqRecv(SeqRecvPath(PortId::default(), ChannelId::default())),
);
}
#[test]
fn sequence_ack_path_parses() {
let path = "nextSequenceAck/ports/defaultPort/channels/channel-0";
let path = Path::from_str(path);
assert!(path.is_ok());
assert_eq!(
path.unwrap(),
Path::SeqAck(SeqAckPath(PortId::default(), ChannelId::default())),
);
}
#[test]
fn test_parse_commitments_fn() {
let path = "commitments/ports/defaultPort/channels/channel-0/sequences/0";
let components: Vec<&str> = path.split('/').collect();
assert_eq!(
parse_commitments(&components),
Some(Path::Commitment(CommitmentPath {
port_id: PortId::default(),
channel_id: ChannelId::default(),
sequence: Sequence::default(),
})),
);
}
#[test]
fn commitments_path_parses() {
let path = "commitments/ports/defaultPort/channels/channel-0/sequences/0";
let path = Path::from_str(path);
assert!(path.is_ok());
assert_eq!(
path.unwrap(),
Path::Commitment(CommitmentPath {
port_id: PortId::default(),
channel_id: ChannelId::default(),
sequence: Sequence::default(),
}),
);
}
#[test]
fn test_parse_acks_fn() {
let path = "acks/ports/defaultPort/channels/channel-0/sequences/0";
let components: Vec<&str> = path.split('/').collect();
assert_eq!(
parse_acks(&components),
Some(Path::Ack(AckPath {
port_id: PortId::default(),
channel_id: ChannelId::default(),
sequence: Sequence::default(),
})),
);
}
#[test]
fn acks_path_parses() {
let path = "acks/ports/defaultPort/channels/channel-0/sequences/0";
let path = Path::from_str(path);
assert!(path.is_ok());
assert_eq!(
path.unwrap(),
Path::Ack(AckPath {
port_id: PortId::default(),
channel_id: ChannelId::default(),
sequence: Sequence::default(),
}),
);
}
#[test]
fn test_parse_receipts_fn() {
let path = "receipts/ports/defaultPort/channels/channel-0/sequences/0";
let components: Vec<&str> = path.split('/').collect();
assert_eq!(
parse_receipts(&components),
Some(Path::Receipt(ReceiptPath {
port_id: PortId::default(),
channel_id: ChannelId::default(),
sequence: Sequence::default(),
})),
);
}
#[test]
fn receipts_path_parses() {
let path = "receipts/ports/defaultPort/channels/channel-0/sequences/0";
let path = Path::from_str(path);
assert!(path.is_ok());
assert_eq!(
path.unwrap(),
Path::Receipt(ReceiptPath {
port_id: PortId::default(),
channel_id: ChannelId::default(),
sequence: Sequence::default(),
}),
);
}
#[test]
fn test_parse_upgrades_fn() {
let path = "upgradedIBCState/0/upgradedClient";
let components: Vec<&str> = path.split('/').collect();
assert_eq!(
parse_upgrades(&components),
Some(Path::Upgrade(ClientUpgradePath::UpgradedClientState(0))),
);
let path = "upgradedIBCState/0/upgradedConsState";
let components: Vec<&str> = path.split('/').collect();
assert_eq!(
parse_upgrades(&components),
Some(Path::Upgrade(
ClientUpgradePath::UpgradedClientConsensusState(0)
)),
)
}
#[test]
fn upgrade_client_state_path_parses() {
let path = "upgradedIBCState/0/upgradedClient";
let path = Path::from_str(path);
assert!(path.is_ok());
assert_eq!(
path.unwrap(),
Path::Upgrade(ClientUpgradePath::UpgradedClientState(0)),
);
}
#[test]
fn upgrade_client_consensus_state_path_parses() {
let path = "upgradedIBCState/0/upgradedConsState";
let path = Path::from_str(path);
assert!(path.is_ok());
assert_eq!(
path.unwrap(),
Path::Upgrade(ClientUpgradePath::UpgradedClientConsensusState(0)),
);
}
}