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

feat: migrate applications module under the ibc crate into ibc-apps #967

Merged
merged 17 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
resolver = "2"
members = [
"crates/ibc",
"crates/ibc-apps",
"crates/ibc-apps/ics20-transfer",
"crates/ibc-apps/ics20-transfer/types",
"crates/ibc-derive",
"crates/ibc-testkit",
"crates/ibc-query",
Expand Down Expand Up @@ -45,7 +48,11 @@ tracing-subscriber = { version = "0.3.17", features = ["fmt", "env-filter", "jso
typed-builder = { version = "0.18.0"}

# ibc dependencies
ibc-derive = { version = "0.3.0", path = "../ibc-derive" }
ibc = { version = "0.47.0", path = "./crates/ibc", default-features = false }
ibc-testkit = { version = "0.47.0", path = "./crates/ibc-testkit", default-features = false}
ibc-app-transfer = { version = "0.47.0", path = "./crates/ibc-apps/ics20-transfer", default-features = false }
ibc-app-transfer-types = { version = "0.47.0", path = "./crates/ibc-apps/ics20-transfer/types", default-features = false }
ibc-derive = { version = "0.3.0", path = "./crates/ibc-derive" }
ibc-proto = { version = "0.38.0", default-features = false }
ics23 = { version = "0.11", default-features = false }

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ the `ibc` rust crate which defines the main data structures and on-chain logic f
## Libraries

- [ibc](crates/ibc/README.md) - Data structures and on-chain logic for the IBC protocol.
- [ibc-apps](crates/ibc-apps/README.md) - Contains implementations of various IBC applications.
- [ibc-derive](crates/ibc-derive/README.md) - Derive macros for `ClientState`
and `ConsensusState` traits, reducing boilerplate.
- [ibc-testkit](crates/ibc-testkit/README.md) - Testing toolkit to aid `ibc-rs` and host chains in writing integration tests.
Expand Down
9 changes: 9 additions & 0 deletions clippy.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
disallowed-types = [
# { path = "usize", reason = "variable size" }, # cannot on now, because mocks use it and serde, even if there is no usize in type
{ path = "f64", reason = "not supported in CosmWasm" },
{ path = "f32", reason = "not supported in CosmWasm" },
]

disallowed-methods = [
"std::time::Duration::as_secs_f64",
]
37 changes: 37 additions & 0 deletions crates/ibc-apps/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[package]
name = "ibc-apps"
version = { workspace = true }
authors = { workspace = true }
edition = { workspace = true }
rust-version = { workspace = true }
license = { workspace = true }
repository = { workspace = true }
keywords = ["blockchain", "cosmos", "ibc", "applications"]
readme = "README.md"
description = """
`ibc-apps` provides a comprehensive set of libraries for IBC applications,
facilitating seamless integration of IBC business logic into any blockchain system.
"""

[package.metadata.docs.rs]
all-features = true

[dependencies]
ibc-app-transfer = { workspace = true }

[features]
default = ["std"]
std = [
"ibc-app-transfer/std",
]
serde = [
"ibc-app-transfer/serde",
]
schema = [
"ibc-app-transfer/schema",
"serde",
"std",
]
borsh = [
"ibc-app-transfer/borsh",
]
48 changes: 48 additions & 0 deletions crates/ibc-apps/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# `ibc-apps`

This crate is a top-level library that re-exports Inter-Blockchain
Communication (IBC) applications implemented in Rust. It serves as a centralized hub,
simplifying the process of importing and integrating various IBC applications
into your blockchain. IBC is a distributed protocol that enables communication
between distinct sovereign blockchains. IBC applications abstract away the core
transport and authentication layers, letter blockchain app developers
focus solely on business logic implementation.

The structure within the `ibc-apps` crate is designed to provide flexibility for
external users. It allows users to either utilize the entire `ibc-apps` crate,
or selectively import specific sub-crates, whether you need a certain IBC
application (e.g. `ibc-app-transfer` crate) or only their associated data
structures (e.g. `ibc-app-transfer-types`). This versatility empowers hosts,
including chain integrators, relayers, or any IBC tooling projects, to build
their solutions on top of the layers that best suit their requirements.

## Libraries

Currently, the `ibc-apps` crate contains the implementation of the following IBC
applications:

### ICS-20: Fungible Token Transfer Application

- [ibc-app-transfer](crates/ibc-apps/ics20-transfer)
- [ibc-app-transfer-types](crates/ibc-apps/ics20-transfer/types)

## Contributing

IBC is specified in English in the [cosmos/ibc repo][ibc]. Any
protocol changes or clarifications should be contributed there.

If you're interested in contributing, please comment on an issue or open a new
one!

See also [CONTRIBUTING.md](./../../CONTRIBUTING.md).

## Resources

- [IBC Website][ibc-homepage]
- [IBC Specification][ibc]
- [IBC Go implementation][ibc-go]

[//]: # (general links)
[ibc]: https://github.com/cosmos/ibc
[ibc-go]: https://github.com/cosmos/ibc-go
[ibc-homepage]: https://cosmos.network/ibc
57 changes: 57 additions & 0 deletions crates/ibc-apps/ics20-transfer/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
[package]
name = "ibc-app-transfer"
version = { workspace = true }
authors = { workspace = true }
edition = { workspace = true }
rust-version = { workspace = true }
license = { workspace = true }
repository = { workspace = true }
keywords = ["blockchain", "cosmos", "ibc", "transfer", "ics20"]
readme = "./../README.md"
description = """
Contains the core implementation of the ICS-20 token transfer application logic
along with re-exporting the data structures from `ibc-app-transfer-types` crate.
"""

[package.metadata.docs.rs]
all-features = true

[dependencies]
# external dependencies
serde_json = { workspace = true, optional = true }
sha2 = { workspace = true }

# ibc dependencies
ibc = { workspace = true }
ibc-app-transfer-types = { workspace = true }

[dev-dependencies]
subtle-encoding = { workspace = true }

[features]
default = ["std"]
std = [
"ibc-app-transfer-types/std",
"ibc/std",
"serde_json/std",
"sha2/std",
]
serde = [
"ibc-app-transfer-types/serde",
"ibc/serde",
"serde_json"
]
schema = [
"ibc-app-transfer-types/schema",
"ibc/schema",
"serde",
"std",
]
borsh = [
"ibc-app-transfer-types/borsh",
"ibc/borsh",
]
parity-scale-codec = [
"ibc-app-transfer-types/parity-scale-codec",
"ibc/parity-scale-codec",
]
136 changes: 136 additions & 0 deletions crates/ibc-apps/ics20-transfer/src/context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
//! Defines the main context traits and IBC module callbacks

use ibc::core::ics24_host::identifier::{ChannelId, PortId};
use ibc::prelude::*;
use ibc::Signer;
use ibc_app_transfer_types::error::TokenTransferError;
use ibc_app_transfer_types::{PrefixedCoin, PrefixedDenom, VERSION};
use sha2::{Digest, Sha256};

/// Methods required in token transfer validation, to be implemented by the host
pub trait TokenTransferValidationContext {
type AccountId: TryFrom<Signer>;

/// get_port returns the portID for the transfer module.
fn get_port(&self) -> Result<PortId, TokenTransferError>;

/// Returns the escrow account id for a port and channel combination
fn get_escrow_account(
&self,
port_id: &PortId,
channel_id: &ChannelId,
) -> Result<Self::AccountId, TokenTransferError>;

/// Returns Ok() if the host chain supports sending coins.
fn can_send_coins(&self) -> Result<(), TokenTransferError>;

/// Returns Ok() if the host chain supports receiving coins.
fn can_receive_coins(&self) -> Result<(), TokenTransferError>;

/// Validates the sender and receiver accounts and the coin inputs
fn send_coins_validate(
&self,
from_account: &Self::AccountId,
to_account: &Self::AccountId,
coin: &PrefixedCoin,
) -> Result<(), TokenTransferError>;

/// Validates the receiver account and the coin input
fn mint_coins_validate(
&self,
account: &Self::AccountId,
coin: &PrefixedCoin,
) -> Result<(), TokenTransferError>;

/// Validates the sender account and the coin input
fn burn_coins_validate(
&self,
account: &Self::AccountId,
coin: &PrefixedCoin,
) -> Result<(), TokenTransferError>;

/// Returns a hash of the prefixed denom.
/// Implement only if the host chain supports hashed denominations.
fn denom_hash_string(&self, _denom: &PrefixedDenom) -> Option<String> {
None
}

Check warning on line 56 in crates/ibc-apps/ics20-transfer/src/context.rs

View check run for this annotation

Codecov / codecov/patch

crates/ibc-apps/ics20-transfer/src/context.rs#L54-L56

Added lines #L54 - L56 were not covered by tests
}

/// Methods required in token transfer execution, to be implemented by the host
pub trait TokenTransferExecutionContext: TokenTransferValidationContext {
/// This function should enable sending ibc fungible tokens from one account to another
fn send_coins_execute(
&mut self,
from_account: &Self::AccountId,
to_account: &Self::AccountId,
coin: &PrefixedCoin,
) -> Result<(), TokenTransferError>;

/// This function to enable minting ibc tokens to a user account
fn mint_coins_execute(
&mut self,
account: &Self::AccountId,
coin: &PrefixedCoin,
) -> Result<(), TokenTransferError>;

/// This function should enable burning of minted tokens in a user account
fn burn_coins_execute(
&mut self,
account: &Self::AccountId,
coin: &PrefixedCoin,
) -> Result<(), TokenTransferError>;
}

/// Helper function to generate an escrow address for a given port and channel
/// ids according to the format specified in the Cosmos SDK
/// [`ADR-028`](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-028-public-key-addresses.md)
pub fn cosmos_adr028_escrow_address(port_id: &PortId, channel_id: &ChannelId) -> Vec<u8> {
let contents = format!("{port_id}/{channel_id}");

let mut hasher = Sha256::new();
hasher.update(VERSION.as_bytes());
hasher.update([0]);
hasher.update(contents.as_bytes());

let mut hash = hasher.finalize().to_vec();
hash.truncate(20);
hash
}

#[cfg(test)]
mod tests {
use subtle_encoding::bech32;

use super::*;
use crate::context::cosmos_adr028_escrow_address;

#[test]
fn test_cosmos_escrow_address() {
fn assert_eq_escrow_address(port_id: &str, channel_id: &str, address: &str) {
let port_id = port_id.parse().unwrap();
let channel_id = channel_id.parse().unwrap();
let gen_address = {
let addr = cosmos_adr028_escrow_address(&port_id, &channel_id);
bech32::encode("cosmos", addr)
};
assert_eq!(gen_address, address.to_owned())
}

// addresses obtained using `gaiad query ibc-transfer escrow-address [port-id] [channel-id]`
assert_eq_escrow_address(
"transfer",
"channel-141",
"cosmos1x54ltnyg88k0ejmk8ytwrhd3ltm84xehrnlslf",
);
assert_eq_escrow_address(
"transfer",
"channel-207",
"cosmos1ju6tlfclulxumtt2kglvnxduj5d93a64r5czge",
);
assert_eq_escrow_address(
"transfer",
"channel-187",
"cosmos177x69sver58mcfs74x6dg0tv6ls4s3xmmcaw53",
);
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
//! Implements the processing logic for ICS20 (token transfer) message.

use super::context::{TokenTransferExecutionContext, TokenTransferValidationContext};
use crate::applications::transfer::error::TokenTransferError;
use crate::applications::transfer::is_sender_chain_source;
use crate::applications::transfer::packet::PacketData;
use crate::core::ics04_channel::packet::Packet;
use crate::prelude::*;

pub mod on_recv_packet;
pub mod send_transfer;

use ibc::core::ics04_channel::packet::Packet;
use ibc::prelude::*;
use ibc_app_transfer_types::error::TokenTransferError;
use ibc_app_transfer_types::is_sender_chain_source;
use ibc_app_transfer_types::packet::PacketData;

use crate::context::{TokenTransferExecutionContext, TokenTransferValidationContext};

pub fn refund_packet_token_execute(
ctx_a: &mut impl TokenTransferExecutionContext,
packet: &Packet,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use crate::applications::transfer::context::TokenTransferExecutionContext;
use crate::applications::transfer::error::TokenTransferError;
use crate::applications::transfer::events::DenomTraceEvent;
use crate::applications::transfer::packet::PacketData;
use crate::applications::transfer::{is_receiver_chain_source, TracePrefix};
use crate::core::ics04_channel::packet::Packet;
use crate::core::router::ModuleExtras;
use crate::prelude::*;
use ibc::core::ics04_channel::packet::Packet;
use ibc::core::router::ModuleExtras;
use ibc::prelude::*;
use ibc_app_transfer_types::error::TokenTransferError;
use ibc_app_transfer_types::events::DenomTraceEvent;
use ibc_app_transfer_types::packet::PacketData;
use ibc_app_transfer_types::{is_receiver_chain_source, TracePrefix};

use crate::context::TokenTransferExecutionContext;

/// This function handles the transfer receiving logic.
///
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
use crate::applications::transfer::context::{
TokenTransferExecutionContext, TokenTransferValidationContext,
};
use crate::applications::transfer::error::TokenTransferError;
use crate::applications::transfer::events::TransferEvent;
use crate::applications::transfer::msgs::transfer::MsgTransfer;
use crate::applications::transfer::{is_sender_chain_source, MODULE_ID_STR};
use crate::core::events::{MessageEvent, ModuleEvent};
use crate::core::ics04_channel::context::{
SendPacketExecutionContext, SendPacketValidationContext,
};
use crate::core::ics04_channel::handler::send_packet::{send_packet_execute, send_packet_validate};
use crate::core::ics04_channel::packet::Packet;
use crate::core::ics24_host::path::{ChannelEndPath, SeqSendPath};
use crate::prelude::*;
use ibc::core::events::{MessageEvent, ModuleEvent};
use ibc::core::ics04_channel::context::{SendPacketExecutionContext, SendPacketValidationContext};
use ibc::core::ics04_channel::handler::send_packet::{send_packet_execute, send_packet_validate};
use ibc::core::ics04_channel::packet::Packet;
use ibc::core::ics24_host::path::{ChannelEndPath, SeqSendPath};
use ibc::prelude::*;
use ibc_app_transfer_types::error::TokenTransferError;
use ibc_app_transfer_types::events::TransferEvent;
use ibc_app_transfer_types::msgs::transfer::MsgTransfer;
use ibc_app_transfer_types::{is_sender_chain_source, MODULE_ID_STR};

use crate::context::{TokenTransferExecutionContext, TokenTransferValidationContext};

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