Skip to content

Commit 68b4ca6

Browse files
feat: migrate applications module under the ibc crate into ibc-apps (#967)
* feat: restructure and split off applications codebase into ibc-apps dir * imp: rename transfer dir to ics20_transfer * feat: add ibc-apps crate * fix: remove redundant dep + fix cargo doc * docs: add README and descriptions * docs: update main README page * nit: docstrings * nit: docstrings * imp: rename folder to ics20-transfer * chore: move serializers into ics20-transfer/types * fix: apply reviewer comments * imp: add docstring for cosmos_adr028_escrow_address * fix: add missing features + use workspace deps for ibc crates * imp: place re-exports under mod * nit: apply suggestions from code review Co-authored-by: Sean Chen <[email protected]> Signed-off-by: Farhad Shabani <[email protected]> * fix: cargo fmt --------- Signed-off-by: Farhad Shabani <[email protected]> Co-authored-by: Sean Chen <[email protected]>
1 parent bf77378 commit 68b4ca6

File tree

40 files changed

+674
-403
lines changed

40 files changed

+674
-403
lines changed

Cargo.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
resolver = "2"
33
members = [
44
"crates/ibc",
5+
"crates/ibc-apps",
6+
"crates/ibc-apps/ics20-transfer",
7+
"crates/ibc-apps/ics20-transfer/types",
58
"crates/ibc-derive",
69
"crates/ibc-testkit",
710
"crates/ibc-query",
@@ -45,7 +48,11 @@ tracing-subscriber = { version = "0.3.17", features = ["fmt", "env-filter", "jso
4548
typed-builder = { version = "0.18.0"}
4649

4750
# ibc dependencies
48-
ibc-derive = { version = "0.3.0", path = "../ibc-derive" }
51+
ibc = { version = "0.47.0", path = "./crates/ibc", default-features = false }
52+
ibc-testkit = { version = "0.47.0", path = "./crates/ibc-testkit", default-features = false}
53+
ibc-app-transfer = { version = "0.47.0", path = "./crates/ibc-apps/ics20-transfer", default-features = false }
54+
ibc-app-transfer-types = { version = "0.47.0", path = "./crates/ibc-apps/ics20-transfer/types", default-features = false }
55+
ibc-derive = { version = "0.3.0", path = "./crates/ibc-derive" }
4956
ibc-proto = { version = "0.38.0", default-features = false }
5057
ics23 = { version = "0.11", default-features = false }
5158

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ the `ibc` rust crate which defines the main data structures and on-chain logic f
2929
## Libraries
3030

3131
- [ibc](crates/ibc/README.md) - Data structures and on-chain logic for the IBC protocol.
32+
- [ibc-apps](crates/ibc-apps/README.md) - Contains implementations of various IBC applications.
3233
- [ibc-derive](crates/ibc-derive/README.md) - Derive macros for `ClientState`
3334
and `ConsensusState` traits, reducing boilerplate.
3435
- [ibc-testkit](crates/ibc-testkit/README.md) - Testing toolkit to aid `ibc-rs` and host chains in writing integration tests.

clippy.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
disallowed-types = [
2+
# { path = "usize", reason = "variable size" }, # cannot on now, because mocks use it and serde, even if there is no usize in type
3+
{ path = "f64", reason = "not supported in CosmWasm" },
4+
{ path = "f32", reason = "not supported in CosmWasm" },
5+
]
6+
7+
disallowed-methods = [
8+
"std::time::Duration::as_secs_f64",
9+
]

crates/ibc-apps/Cargo.toml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
[package]
2+
name = "ibc-apps"
3+
version = { workspace = true }
4+
authors = { workspace = true }
5+
edition = { workspace = true }
6+
rust-version = { workspace = true }
7+
license = { workspace = true }
8+
repository = { workspace = true }
9+
keywords = ["blockchain", "cosmos", "ibc", "applications"]
10+
readme = "README.md"
11+
description = """
12+
`ibc-apps` provides a comprehensive set of libraries for IBC applications,
13+
facilitating seamless integration of IBC business logic into any blockchain system.
14+
"""
15+
16+
[package.metadata.docs.rs]
17+
all-features = true
18+
19+
[dependencies]
20+
ibc-app-transfer = { workspace = true }
21+
22+
[features]
23+
default = ["std"]
24+
std = [
25+
"ibc-app-transfer/std",
26+
]
27+
serde = [
28+
"ibc-app-transfer/serde",
29+
]
30+
schema = [
31+
"ibc-app-transfer/schema",
32+
"serde",
33+
"std",
34+
]
35+
borsh = [
36+
"ibc-app-transfer/borsh",
37+
]

crates/ibc-apps/README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# `ibc-apps`
2+
3+
This crate is a top-level library that re-exports Inter-Blockchain
4+
Communication (IBC) applications implemented in Rust. It serves as a centralized hub,
5+
simplifying the process of importing and integrating various IBC applications
6+
into your blockchain. IBC is a distributed protocol that enables communication
7+
between distinct sovereign blockchains. IBC applications abstract away the core
8+
transport and authentication layers, letter blockchain app developers
9+
focus solely on business logic implementation.
10+
11+
The structure within the `ibc-apps` crate is designed to provide flexibility for
12+
external users. It allows users to either utilize the entire `ibc-apps` crate,
13+
or selectively import specific sub-crates, whether you need a certain IBC
14+
application (e.g. `ibc-app-transfer` crate) or only their associated data
15+
structures (e.g. `ibc-app-transfer-types`). This versatility empowers hosts,
16+
including chain integrators, relayers, or any IBC tooling projects, to build
17+
their solutions on top of the layers that best suit their requirements.
18+
19+
## Libraries
20+
21+
Currently, the `ibc-apps` crate contains the implementation of the following IBC
22+
applications:
23+
24+
### ICS-20: Fungible Token Transfer Application
25+
26+
- [ibc-app-transfer](crates/ibc-apps/ics20-transfer)
27+
- [ibc-app-transfer-types](crates/ibc-apps/ics20-transfer/types)
28+
29+
## Contributing
30+
31+
IBC is specified in English in the [cosmos/ibc repo][ibc]. Any
32+
protocol changes or clarifications should be contributed there.
33+
34+
If you're interested in contributing, please comment on an issue or open a new
35+
one!
36+
37+
See also [CONTRIBUTING.md](./../../CONTRIBUTING.md).
38+
39+
## Resources
40+
41+
- [IBC Website][ibc-homepage]
42+
- [IBC Specification][ibc]
43+
- [IBC Go implementation][ibc-go]
44+
45+
[//]: # (general links)
46+
[ibc]: https://github.com/cosmos/ibc
47+
[ibc-go]: https://github.com/cosmos/ibc-go
48+
[ibc-homepage]: https://cosmos.network/ibc
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
[package]
2+
name = "ibc-app-transfer"
3+
version = { workspace = true }
4+
authors = { workspace = true }
5+
edition = { workspace = true }
6+
rust-version = { workspace = true }
7+
license = { workspace = true }
8+
repository = { workspace = true }
9+
keywords = ["blockchain", "cosmos", "ibc", "transfer", "ics20"]
10+
readme = "./../README.md"
11+
description = """
12+
Contains the core implementation of the ICS-20 token transfer application logic
13+
along with re-exporting the data structures from `ibc-app-transfer-types` crate.
14+
"""
15+
16+
[package.metadata.docs.rs]
17+
all-features = true
18+
19+
[dependencies]
20+
# external dependencies
21+
serde_json = { workspace = true, optional = true }
22+
sha2 = { workspace = true }
23+
24+
# ibc dependencies
25+
ibc = { workspace = true }
26+
ibc-app-transfer-types = { workspace = true }
27+
28+
[dev-dependencies]
29+
subtle-encoding = { workspace = true }
30+
31+
[features]
32+
default = ["std"]
33+
std = [
34+
"ibc-app-transfer-types/std",
35+
"ibc/std",
36+
"serde_json/std",
37+
"sha2/std",
38+
]
39+
serde = [
40+
"ibc-app-transfer-types/serde",
41+
"ibc/serde",
42+
"serde_json"
43+
]
44+
schema = [
45+
"ibc-app-transfer-types/schema",
46+
"ibc/schema",
47+
"serde",
48+
"std",
49+
]
50+
borsh = [
51+
"ibc-app-transfer-types/borsh",
52+
"ibc/borsh",
53+
]
54+
parity-scale-codec = [
55+
"ibc-app-transfer-types/parity-scale-codec",
56+
"ibc/parity-scale-codec",
57+
]
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
//! Defines the main context traits and IBC module callbacks
2+
3+
use ibc::core::ics24_host::identifier::{ChannelId, PortId};
4+
use ibc::prelude::*;
5+
use ibc::Signer;
6+
use ibc_app_transfer_types::error::TokenTransferError;
7+
use ibc_app_transfer_types::{PrefixedCoin, PrefixedDenom, VERSION};
8+
use sha2::{Digest, Sha256};
9+
10+
/// Methods required in token transfer validation, to be implemented by the host
11+
pub trait TokenTransferValidationContext {
12+
type AccountId: TryFrom<Signer>;
13+
14+
/// get_port returns the portID for the transfer module.
15+
fn get_port(&self) -> Result<PortId, TokenTransferError>;
16+
17+
/// Returns the escrow account id for a port and channel combination
18+
fn get_escrow_account(
19+
&self,
20+
port_id: &PortId,
21+
channel_id: &ChannelId,
22+
) -> Result<Self::AccountId, TokenTransferError>;
23+
24+
/// Returns Ok() if the host chain supports sending coins.
25+
fn can_send_coins(&self) -> Result<(), TokenTransferError>;
26+
27+
/// Returns Ok() if the host chain supports receiving coins.
28+
fn can_receive_coins(&self) -> Result<(), TokenTransferError>;
29+
30+
/// Validates the sender and receiver accounts and the coin inputs
31+
fn send_coins_validate(
32+
&self,
33+
from_account: &Self::AccountId,
34+
to_account: &Self::AccountId,
35+
coin: &PrefixedCoin,
36+
) -> Result<(), TokenTransferError>;
37+
38+
/// Validates the receiver account and the coin input
39+
fn mint_coins_validate(
40+
&self,
41+
account: &Self::AccountId,
42+
coin: &PrefixedCoin,
43+
) -> Result<(), TokenTransferError>;
44+
45+
/// Validates the sender account and the coin input
46+
fn burn_coins_validate(
47+
&self,
48+
account: &Self::AccountId,
49+
coin: &PrefixedCoin,
50+
) -> Result<(), TokenTransferError>;
51+
52+
/// Returns a hash of the prefixed denom.
53+
/// Implement only if the host chain supports hashed denominations.
54+
fn denom_hash_string(&self, _denom: &PrefixedDenom) -> Option<String> {
55+
None
56+
}
57+
}
58+
59+
/// Methods required in token transfer execution, to be implemented by the host
60+
pub trait TokenTransferExecutionContext: TokenTransferValidationContext {
61+
/// This function should enable sending ibc fungible tokens from one account to another
62+
fn send_coins_execute(
63+
&mut self,
64+
from_account: &Self::AccountId,
65+
to_account: &Self::AccountId,
66+
coin: &PrefixedCoin,
67+
) -> Result<(), TokenTransferError>;
68+
69+
/// This function to enable minting ibc tokens to a user account
70+
fn mint_coins_execute(
71+
&mut self,
72+
account: &Self::AccountId,
73+
coin: &PrefixedCoin,
74+
) -> Result<(), TokenTransferError>;
75+
76+
/// This function should enable burning of minted tokens in a user account
77+
fn burn_coins_execute(
78+
&mut self,
79+
account: &Self::AccountId,
80+
coin: &PrefixedCoin,
81+
) -> Result<(), TokenTransferError>;
82+
}
83+
84+
/// Helper function to generate an escrow address for a given port and channel
85+
/// ids according to the format specified in the Cosmos SDK
86+
/// [`ADR-028`](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-028-public-key-addresses.md)
87+
pub fn cosmos_adr028_escrow_address(port_id: &PortId, channel_id: &ChannelId) -> Vec<u8> {
88+
let contents = format!("{port_id}/{channel_id}");
89+
90+
let mut hasher = Sha256::new();
91+
hasher.update(VERSION.as_bytes());
92+
hasher.update([0]);
93+
hasher.update(contents.as_bytes());
94+
95+
let mut hash = hasher.finalize().to_vec();
96+
hash.truncate(20);
97+
hash
98+
}
99+
100+
#[cfg(test)]
101+
mod tests {
102+
use subtle_encoding::bech32;
103+
104+
use super::*;
105+
use crate::context::cosmos_adr028_escrow_address;
106+
107+
#[test]
108+
fn test_cosmos_escrow_address() {
109+
fn assert_eq_escrow_address(port_id: &str, channel_id: &str, address: &str) {
110+
let port_id = port_id.parse().unwrap();
111+
let channel_id = channel_id.parse().unwrap();
112+
let gen_address = {
113+
let addr = cosmos_adr028_escrow_address(&port_id, &channel_id);
114+
bech32::encode("cosmos", addr)
115+
};
116+
assert_eq!(gen_address, address.to_owned())
117+
}
118+
119+
// addresses obtained using `gaiad query ibc-transfer escrow-address [port-id] [channel-id]`
120+
assert_eq_escrow_address(
121+
"transfer",
122+
"channel-141",
123+
"cosmos1x54ltnyg88k0ejmk8ytwrhd3ltm84xehrnlslf",
124+
);
125+
assert_eq_escrow_address(
126+
"transfer",
127+
"channel-207",
128+
"cosmos1ju6tlfclulxumtt2kglvnxduj5d93a64r5czge",
129+
);
130+
assert_eq_escrow_address(
131+
"transfer",
132+
"channel-187",
133+
"cosmos177x69sver58mcfs74x6dg0tv6ls4s3xmmcaw53",
134+
);
135+
}
136+
}

crates/ibc/src/applications/transfer/relay.rs renamed to crates/ibc-apps/ics20-transfer/src/handler/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
//! Implements the processing logic for ICS20 (token transfer) message.
2-
3-
use super::context::{TokenTransferExecutionContext, TokenTransferValidationContext};
4-
use crate::applications::transfer::error::TokenTransferError;
5-
use crate::applications::transfer::is_sender_chain_source;
6-
use crate::applications::transfer::packet::PacketData;
7-
use crate::core::ics04_channel::packet::Packet;
8-
use crate::prelude::*;
9-
102
pub mod on_recv_packet;
113
pub mod send_transfer;
124

5+
use ibc::core::ics04_channel::packet::Packet;
6+
use ibc::prelude::*;
7+
use ibc_app_transfer_types::error::TokenTransferError;
8+
use ibc_app_transfer_types::is_sender_chain_source;
9+
use ibc_app_transfer_types::packet::PacketData;
10+
11+
use crate::context::{TokenTransferExecutionContext, TokenTransferValidationContext};
12+
1313
pub fn refund_packet_token_execute(
1414
ctx_a: &mut impl TokenTransferExecutionContext,
1515
packet: &Packet,

crates/ibc/src/applications/transfer/relay/on_recv_packet.rs renamed to crates/ibc-apps/ics20-transfer/src/handler/on_recv_packet.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
use crate::applications::transfer::context::TokenTransferExecutionContext;
2-
use crate::applications::transfer::error::TokenTransferError;
3-
use crate::applications::transfer::events::DenomTraceEvent;
4-
use crate::applications::transfer::packet::PacketData;
5-
use crate::applications::transfer::{is_receiver_chain_source, TracePrefix};
6-
use crate::core::ics04_channel::packet::Packet;
7-
use crate::core::router::ModuleExtras;
8-
use crate::prelude::*;
1+
use ibc::core::ics04_channel::packet::Packet;
2+
use ibc::core::router::ModuleExtras;
3+
use ibc::prelude::*;
4+
use ibc_app_transfer_types::error::TokenTransferError;
5+
use ibc_app_transfer_types::events::DenomTraceEvent;
6+
use ibc_app_transfer_types::packet::PacketData;
7+
use ibc_app_transfer_types::{is_receiver_chain_source, TracePrefix};
8+
9+
use crate::context::TokenTransferExecutionContext;
910

1011
/// This function handles the transfer receiving logic.
1112
///

crates/ibc/src/applications/transfer/relay/send_transfer.rs renamed to crates/ibc-apps/ics20-transfer/src/handler/send_transfer.rs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
1-
use crate::applications::transfer::context::{
2-
TokenTransferExecutionContext, TokenTransferValidationContext,
3-
};
4-
use crate::applications::transfer::error::TokenTransferError;
5-
use crate::applications::transfer::events::TransferEvent;
6-
use crate::applications::transfer::msgs::transfer::MsgTransfer;
7-
use crate::applications::transfer::{is_sender_chain_source, MODULE_ID_STR};
8-
use crate::core::events::{MessageEvent, ModuleEvent};
9-
use crate::core::ics04_channel::context::{
10-
SendPacketExecutionContext, SendPacketValidationContext,
11-
};
12-
use crate::core::ics04_channel::handler::send_packet::{send_packet_execute, send_packet_validate};
13-
use crate::core::ics04_channel::packet::Packet;
14-
use crate::core::ics24_host::path::{ChannelEndPath, SeqSendPath};
15-
use crate::prelude::*;
1+
use ibc::core::events::{MessageEvent, ModuleEvent};
2+
use ibc::core::ics04_channel::context::{SendPacketExecutionContext, SendPacketValidationContext};
3+
use ibc::core::ics04_channel::handler::send_packet::{send_packet_execute, send_packet_validate};
4+
use ibc::core::ics04_channel::packet::Packet;
5+
use ibc::core::ics24_host::path::{ChannelEndPath, SeqSendPath};
6+
use ibc::prelude::*;
7+
use ibc_app_transfer_types::error::TokenTransferError;
8+
use ibc_app_transfer_types::events::TransferEvent;
9+
use ibc_app_transfer_types::msgs::transfer::MsgTransfer;
10+
use ibc_app_transfer_types::{is_sender_chain_source, MODULE_ID_STR};
11+
12+
use crate::context::{TokenTransferExecutionContext, TokenTransferValidationContext};
1613

1714
/// Initiate a token transfer. Equivalent to calling [`send_transfer_validate`], followed by [`send_transfer_execute`].
1815
pub fn send_transfer<SendPacketCtx, TokenCtx>(

0 commit comments

Comments
 (0)