Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/interchain core #503

Merged
merged 13 commits into from
Oct 8, 2024
4 changes: 1 addition & 3 deletions cw-orch-interchain/examples/doc_daemon.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use cw_orch::prelude::networks::{LOCAL_JUNO, LOCAL_MIGALOO, LOCAL_OSMO};
use cw_orch::prelude::*;
use cw_orch_interchain::{
ChannelCreationValidator, ChannelCreator, DaemonInterchain, InterchainEnv, Starship,
};
use cw_orch_interchain::prelude::*;

fn create_daemon_env() -> cw_orch::anyhow::Result<DaemonInterchain> {
// ANCHOR: DAEMON_INTERCHAIN_CREATION
Expand Down
2 changes: 1 addition & 1 deletion cw-orch-interchain/examples/doc_mock.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use cw_orch::prelude::*;
use cw_orch_interchain::{InterchainEnv, MockInterchainEnv};
use cw_orch_interchain::prelude::*;
use ibc_relayer_types::core::ics24_host::identifier::PortId;

fn crate_mock_env() -> cw_orch::anyhow::Result<MockInterchainEnv> {
Expand Down
2 changes: 1 addition & 1 deletion cw-orch-interchain/examples/follow_packets_txhash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use cw_orch::{
environment::{ChainInfo, NetworkInfo},
prelude::networks::osmosis::OSMOSIS_1,
};
use cw_orch_interchain_daemon::{ChannelCreationValidator, DaemonInterchain};
use cw_orch_interchain::prelude::*;

pub const NOBLE: NetworkInfo = NetworkInfo {
chain_name: "noble",
Expand Down
10 changes: 5 additions & 5 deletions cw-orch-interchain/examples/timeout_packet.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use cosmos_sdk_proto::traits::{Message, Name};
use cw_orch::{environment::QueryHandler, prelude::*};
use cw_orch_interchain_core::InterchainEnv;
use cw_orch_interchain_daemon::ChannelCreator as _;
use cw_orch_interchain::prelude::*;
use cw_orch_interchain_core::IbcPacketOutcome;
use cw_orch_starship::Starship;
use ibc_proto::ibc::{
applications::transfer::v1::{MsgTransfer, MsgTransferResponse},
Expand Down Expand Up @@ -59,9 +59,9 @@ fn main() -> cw_orch::anyhow::Result<()> {

let result = interchain.await_packets("juno-1", tx_resp)?;

match &result.packets[0].outcome {
cw_orch_interchain_core::types::IbcPacketOutcome::Timeout { .. } => {}
cw_orch_interchain_core::types::IbcPacketOutcome::Success { .. } => {
match &result.packets[0] {
IbcPacketOutcome::Timeout { .. } => {}
IbcPacketOutcome::Success { .. } => {
panic!("Expected timeout")
}
}
Expand Down
18 changes: 13 additions & 5 deletions cw-orch-interchain/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#[cfg(not(target_arch = "wasm32"))]
pub mod prelude {
pub use cw_orch_interchain_core::{
types::ChannelCreationResult, IbcQueryHandler, InterchainEnv,
results::ChannelCreationResult, IbcQueryHandler, InterchainEnv, PacketAnalysis,
};
pub use cw_orch_interchain_mock::{MockBech32InterchainEnv, MockInterchainEnv};

Expand All @@ -20,15 +20,23 @@ pub mod prelude {
}

#[cfg(not(target_arch = "wasm32"))]
pub use cw_orch_interchain_core::*;
pub mod core {
pub use cw_orch_interchain_core::*;
}

#[cfg(not(target_arch = "wasm32"))]
pub use cw_orch_interchain_mock::*;
pub mod mock {
pub use cw_orch_interchain_mock::*;
}

#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "daemon")]
pub use cw_orch_interchain_daemon::*;
pub mod daemon {
pub use cw_orch_interchain_daemon::*;
}

#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "daemon")]
pub use cw_orch_starship::*;
pub mod starship {
pub use cw_orch_starship::*;
}
6 changes: 3 additions & 3 deletions cw-orch-interchain/tests/timeout_packet_mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ fn timeout_packet_mock() -> cw_orch::anyhow::Result<()> {

let result = interchain.await_packets("juno-1", tx_resp)?;

match &result.packets[0].outcome {
cw_orch_interchain_core::types::IbcPacketOutcome::Timeout { .. } => {}
cw_orch_interchain_core::types::IbcPacketOutcome::Success { .. } => {
match &result.packets[0] {
cw_orch_interchain_core::IbcPacketOutcome::Timeout { .. } => {}
cw_orch_interchain_core::IbcPacketOutcome::Success { .. } => {
panic!("Expected timeout")
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/integrations/cw-plus/tests/interface_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ mod cw20_ics {
msg::AllowedInfo,
};
use cw_orch::prelude::*;
use cw_orch_interchain::{env::contract_port, prelude::*};
use cw_orch_interchain::{core::contract_port, prelude::*};
use cw_plus_orch::{
cw20_base::{Cw20Base, ExecuteMsgInterfaceFns as _},
cw20_ics20::{
Expand Down
75 changes: 41 additions & 34 deletions packages/interchain/interchain-core/src/ack_parser.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{from_json, Binary};
use cw_orch_core::environment::CwEnv;
use prost::Message;
// TODO: when polytone updates to cosmwasm v2 use polytone::ack::Callback;
use polytone_callback::Callback;

use crate::{
env::decode_ack_error,
types::{parse::SuccessIbcPacket, IbcTxAnalysis},
InterchainError,
};
use crate::{packet::success::SuccessfullAck, InterchainError};

use self::acknowledgement::{Acknowledgement, Response};

/// Struct used to centralize all the pre-defined ack types
pub enum IbcAckParser {}

impl IbcAckParser {
/// Verifies if the given ack is an Polytone type and returns the acknowledgement if it is
/// Verifies if the given ack is an Polytone type and returns the parsed acknowledgement if it is
///
/// Returns an error if there was an error in the process
pub fn polytone_ack(ack: &Binary) -> Result<Callback, InterchainError> {
Expand Down Expand Up @@ -83,6 +78,44 @@
}
Err(decode_ack_error(ack))
}

/// Verifies if the given ack is a standard acknowledgement type
///
/// Returns an error if there was an error in the parsing process
pub fn any_standard_ack(ack: &Binary) -> Result<SuccessfullAck, InterchainError> {
if let Ok(ack) = IbcAckParser::polytone_ack(ack) {
Ok(SuccessfullAck::Polytone(ack))

Check warning on line 87 in packages/interchain/interchain-core/src/ack_parser.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/ack_parser.rs#L87

Added line #L87 was not covered by tests
} else if IbcAckParser::ics20_ack(ack).is_ok() {
Ok(SuccessfullAck::Ics20)
} else if let Ok(ack) = IbcAckParser::ics004_ack(ack) {
Ok(SuccessfullAck::Ics004(ack))

Check warning on line 91 in packages/interchain/interchain-core/src/ack_parser.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/ack_parser.rs#L90-L91

Added lines #L90 - L91 were not covered by tests
} else {
Err(InterchainError::AckDecodingFailed(
ack.clone(),
String::from_utf8_lossy(ack.as_slice()).to_string(),
))

Check warning on line 96 in packages/interchain/interchain-core/src/ack_parser.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/ack_parser.rs#L93-L96

Added lines #L93 - L96 were not covered by tests
}
}

/// Verifies if the given ack custom acknowledgement type.
/// If it fails, tries to parse into standard ack types
///
/// Returns an error if there was an error in the parsing process
pub fn any_standard_ack_with_custom<CustomOutcome>(
ack: &Binary,
parsing_func: fn(&Binary) -> Result<CustomOutcome, InterchainError>,
) -> Result<SuccessfullAck<CustomOutcome>, InterchainError> {
parsing_func(ack)
.map(SuccessfullAck::Custom)
.or_else(|_| Self::any_standard_ack(ack).map(|ack| ack.into_custom()))
}

Check warning on line 111 in packages/interchain/interchain-core/src/ack_parser.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/ack_parser.rs#L104-L111

Added lines #L104 - L111 were not covered by tests
}

pub(crate) fn decode_ack_error(ack: &Binary) -> InterchainError {
InterchainError::AckDecodingFailed(
ack.clone(),
String::from_utf8_lossy(ack.as_slice()).to_string(),
)
}

#[cw_serde]
Expand All @@ -94,32 +127,6 @@
Error(String),
}

impl<Chain: CwEnv> IbcTxAnalysis<Chain> {
/// Assert that all packets were not timeout
pub fn assert_no_timeout(&self) -> Result<Vec<SuccessIbcPacket<Chain>>, InterchainError> {
Ok(self
.packets
.iter()
.map(|p| p.assert_no_timeout())
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.flatten()
.collect())
}

/// Returns all packets that were successful without asserting there was no timeout
pub fn get_success_packets(&self) -> Result<Vec<SuccessIbcPacket<Chain>>, InterchainError> {
Ok(self
.packets
.iter()
.map(|p| p.get_success_packets())
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.flatten()
.collect())
}
}

/// This is copied from https://github.com/cosmos/cosmos-rust/blob/4f2e3bbf9c67c8ffef44ef1e485a327fd66f060a/cosmos-sdk-proto/src/prost/ibc-go/ibc.core.channel.v1.rs#L164
/// This is the ICS-004 standard proposal
pub mod acknowledgement {
Expand Down Expand Up @@ -149,7 +156,7 @@
}
}

mod polytone_callback {
pub mod polytone_callback {
use super::*;

use cosmwasm_std::{SubMsgResponse, Uint64};
Expand Down
172 changes: 172 additions & 0 deletions packages/interchain/interchain-core/src/analysis.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
//! Analysis of committed IBC related Txs and Packets.

use crate::packet::success::{SuccessNestedPacketsFlow, SuccessSinglePacketFlow};
use crate::packet::{
success::SuccessIbcPacketOutcome, IbcPacketOutcome, NestedPacketsFlow, SinglePacketFlow,
};
use crate::tx::TxId;
use crate::{IbcAckParser, InterchainError};
use cosmwasm_std::{Binary, Empty};
use cw_orch_core::environment::CwEnv;

/// Trait used for analysis of IBC packet flows
pub trait PacketAnalysis {
/// Result of the Analysis of the packet flows
type AnalysisResult<CustomOutcome>;

/// Asserts that there is no timeout packet inside the result structure.
fn assert_no_timeout(&self) -> Result<(), InterchainError>;

/// Tries to parses all acknowledgements into standard acknowledgments (polytone, ics20 or ics004).
/// Errors if some packet doesn't conform to those results.
fn into_result(self) -> Result<Self::AnalysisResult<Empty>, InterchainError>;

/// Tries to parses all acknowledgements into `CustomOutcome` using a custom parsing function.
///
/// If it fails, also tries with standard acknowledgements (polytone, ics20 or ics004).
/// Errors if some packet doesn't conform to those results.
fn into_result_custom<CustomOutcome>(
self,
parse_func: fn(&Binary) -> Result<CustomOutcome, InterchainError>,
) -> Result<Self::AnalysisResult<CustomOutcome>, InterchainError>;
}

impl<Chain: CwEnv> PacketAnalysis for TxId<Chain, Empty> {
type AnalysisResult<CustomOutcome> = TxId<Chain, CustomOutcome>;

fn assert_no_timeout(&self) -> Result<(), InterchainError> {
Ok(())
}

Check warning on line 39 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L37-L39

Added lines #L37 - L39 were not covered by tests

fn into_result(self) -> Result<Self::AnalysisResult<Empty>, InterchainError> {
Ok(self)
}

Check warning on line 43 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L41-L43

Added lines #L41 - L43 were not covered by tests

fn into_result_custom<CustomOutcome>(
self,
_funcs: fn(&Binary) -> Result<CustomOutcome, InterchainError>,
) -> Result<Self::AnalysisResult<CustomOutcome>, InterchainError> {
Ok(TxId::new(self.chain_id, self.response))
}

Check warning on line 50 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L45-L50

Added lines #L45 - L50 were not covered by tests
}

impl<T: PacketAnalysis> PacketAnalysis for IbcPacketOutcome<T> {
type AnalysisResult<CustomOutcome> =
SuccessIbcPacketOutcome<T::AnalysisResult<CustomOutcome>, CustomOutcome>;

fn assert_no_timeout(&self) -> Result<(), InterchainError> {
match &self {
IbcPacketOutcome::Success { .. } => Ok(()),
IbcPacketOutcome::Timeout { .. } => Err(InterchainError::PacketTimeout {}),

Check warning on line 60 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L57-L60

Added lines #L57 - L60 were not covered by tests
}
}

Check warning on line 62 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L62

Added line #L62 was not covered by tests

fn into_result(self) -> Result<Self::AnalysisResult<Empty>, InterchainError> {
match self {
IbcPacketOutcome::Success {
receive_tx,
ack_tx,
ack,
} => {
let successful_ack = IbcAckParser::any_standard_ack(&ack)?;
Ok(SuccessIbcPacketOutcome {
receive_tx: receive_tx.into_result()?,
ack_tx: ack_tx.into_result()?,
ack: successful_ack,
})
}
IbcPacketOutcome::Timeout { .. } => Err(InterchainError::PacketTimeout {}),

Check warning on line 78 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L78

Added line #L78 was not covered by tests
}
}

fn into_result_custom<CustomOutcome>(
self,
parsing_func: fn(&Binary) -> Result<CustomOutcome, InterchainError>,
) -> Result<Self::AnalysisResult<CustomOutcome>, InterchainError> {
match self {

Check warning on line 86 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L82-L86

Added lines #L82 - L86 were not covered by tests
IbcPacketOutcome::Success {
receive_tx,
ack_tx,
ack,

Check warning on line 90 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L88-L90

Added lines #L88 - L90 were not covered by tests
} => {
let successful_ack =
IbcAckParser::any_standard_ack_with_custom(&ack, parsing_func)?;

Check warning on line 93 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L92-L93

Added lines #L92 - L93 were not covered by tests
Ok(SuccessIbcPacketOutcome {
receive_tx: receive_tx.into_result_custom(parsing_func)?,
ack_tx: ack_tx.into_result_custom(parsing_func)?,
ack: successful_ack,

Check warning on line 97 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L95-L97

Added lines #L95 - L97 were not covered by tests
})
}
IbcPacketOutcome::Timeout { .. } => Err(InterchainError::PacketTimeout {}),

Check warning on line 100 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L100

Added line #L100 was not covered by tests
}
}

Check warning on line 102 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L102

Added line #L102 was not covered by tests
}
impl<Chain: CwEnv> PacketAnalysis for SinglePacketFlow<Chain> {
type AnalysisResult<CustomOutcome> = SuccessSinglePacketFlow<Chain, CustomOutcome>;

fn assert_no_timeout(&self) -> Result<(), InterchainError> {
self.outcome.assert_no_timeout()
}

Check warning on line 109 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L107-L109

Added lines #L107 - L109 were not covered by tests

fn into_result(self) -> Result<Self::AnalysisResult<Empty>, InterchainError> {
let success = self.outcome.into_result()?;

Check warning on line 112 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L111-L112

Added lines #L111 - L112 were not covered by tests

Ok(SuccessSinglePacketFlow {
send_tx: self.send_tx,
outcome: success,
})
}

Check warning on line 118 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L114-L118

Added lines #L114 - L118 were not covered by tests

fn into_result_custom<CustomOutcome>(
self,
parse_func: fn(&Binary) -> Result<CustomOutcome, InterchainError>,
) -> Result<Self::AnalysisResult<CustomOutcome>, InterchainError> {
let success = self.outcome.into_result_custom(parse_func)?;

Check warning on line 124 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L120-L124

Added lines #L120 - L124 were not covered by tests

Ok(SuccessSinglePacketFlow::<Chain, CustomOutcome> {
send_tx: self.send_tx,
outcome: success,
})
}

Check warning on line 130 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L126-L130

Added lines #L126 - L130 were not covered by tests
}

impl<Chain: CwEnv> PacketAnalysis for NestedPacketsFlow<Chain> {
type AnalysisResult<CustomOutcome> = SuccessNestedPacketsFlow<Chain, CustomOutcome>;

fn assert_no_timeout(&self) -> Result<(), InterchainError> {
self.packets
.iter()
.map(|p| p.assert_no_timeout())
.collect::<Result<Vec<_>, _>>()?;
Ok(())
}

Check warning on line 142 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L136-L142

Added lines #L136 - L142 were not covered by tests

fn into_result(self) -> Result<Self::AnalysisResult<Empty>, InterchainError> {
let packets = self
.packets
.into_iter()
.map(|p| p.into_result())
.collect::<Result<Vec<_>, _>>()?;

Ok(SuccessNestedPacketsFlow {
tx_id: self.tx_id,
packets,
})
}

fn into_result_custom<CustomOutcome>(
self,
parse_func: fn(&Binary) -> Result<CustomOutcome, InterchainError>,
) -> Result<Self::AnalysisResult<CustomOutcome>, InterchainError> {
let packets = self
.packets
.into_iter()
.map(|p| p.into_result_custom(parse_func))
.collect::<Result<Vec<_>, _>>()?;

Check warning on line 165 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L157-L165

Added lines #L157 - L165 were not covered by tests

Ok(SuccessNestedPacketsFlow {
tx_id: self.tx_id,
packets,
})
}

Check warning on line 171 in packages/interchain/interchain-core/src/analysis.rs

View check run for this annotation

Codecov / codecov/patch

packages/interchain/interchain-core/src/analysis.rs#L167-L171

Added lines #L167 - L171 were not covered by tests
}
Loading
Loading