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

ICS29: Add fee transfer command #2682

Merged
merged 13 commits into from
Oct 10, 2022
Merged
Show file tree
Hide file tree
Changes from 12 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- New command `fee transfer` which transfers tokens with fees
([#2714](https://github.com/informalsystems/ibc-rs/issues/2714))
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ exclude = [
]

[patch.crates-io]
ibc-proto = { git = "https://github.com/cosmos/ibc-proto-rs", branch = "romac/ibc-v5" }
ibc-proto = { git = "https://github.com/cosmos/ibc-proto-rs" }
# tendermint = { git = "https://github.com/informalsystems/tendermint-rs", branch = "v0.23.x" }
# tendermint-rpc = { git = "https://github.com/informalsystems/tendermint-rs", branch = "v0.23.x" }
# tendermint-proto = { git = "https://github.com/informalsystems/tendermint-rs", branch = "v0.23.x" }
Expand Down
2 changes: 1 addition & 1 deletion ci/no-std-check/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ substrate-std = [
]

[patch.crates-io]
ibc-proto = { git = "https://github.com/cosmos/ibc-proto-rs", branch = "romac/ibc-v5" }
ibc-proto = { git = "https://github.com/cosmos/ibc-proto-rs" }
# tendermint = { git = "https://github.com/informalsystems/tendermint-rs", branch = "v0.23.x" }
# tendermint-proto = { git = "https://github.com/informalsystems/tendermint-rs", branch = "v0.23.x" }
# tendermint-light-client-verifier = { git = "https://github.com/informalsystems/tendermint-rs", branch = "v0.23.x" }
88 changes: 86 additions & 2 deletions crates/relayer-cli/src/cli_utils.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
//! Various utilities for the Hermes CLI

use alloc::sync::Arc;

use eyre::eyre;
use tokio::runtime::Runtime as TokioRuntime;
use tracing::debug;

use ibc::core::ics02_client::client_state::ClientState;
use ibc::core::ics24_host::identifier::{ChainId, ChannelId, PortId};

use ibc_relayer::chain::requests::{
IncludeProof, QueryChannelRequest, QueryClientStateRequest, QueryConnectionRequest, QueryHeight,
};
use ibc_relayer::{
chain::{
counterparty::{channel_connection_client, ChannelConnectionClient},
Expand Down Expand Up @@ -102,3 +105,84 @@ pub fn spawn_chain_counterparty<Chain: ChainHandle>(
channel_connection_client,
))
}

/// Check that the relayer can send on the given channel and ensure that channels and chain identifiers match.
/// To do this, fetch from the source chain the channel end, then the associated connection
/// end, and then the underlying client state; finally, check that this client is verifying
/// headers for the destination chain.
pub fn check_can_send_on_channel<Chain: ChainHandle>(
src_chain: &Chain,
src_channel_id: &ChannelId,
src_port_id: &PortId,
dst_chain_id: &ChainId,
) -> Result<(), eyre::Report> {
// Fetch from the source chain the channel end and check that it is open.
let (channel_end_src, _) = src_chain.query_channel(
QueryChannelRequest {
port_id: src_port_id.clone(),
channel_id: src_channel_id.clone(),
height: QueryHeight::Latest,
},
IncludeProof::No,
)?;

if !channel_end_src.is_open() {
return Err(eyre!(
"the requested port/channel ('{}'/'{}') on chain id '{}' is in state '{}'; expected 'open' state",
src_port_id,
src_channel_id,
src_chain.id(),
channel_end_src.state
));
}

let conn_id = match channel_end_src.connection_hops.first() {
Some(cid) => cid,
None => {
return Err(eyre!(
"could not retrieve the connection hop underlying port/channel '{}'/'{}' on chain '{}'",
src_port_id, src_channel_id, src_chain.id()
));
}
};

// Fetch the associated connection end.
let (conn_end, _) = src_chain.query_connection(
QueryConnectionRequest {
connection_id: conn_id.clone(),
height: QueryHeight::Latest,
},
IncludeProof::No,
)?;

debug!("connection hop underlying the channel: {:?}", conn_end);

// Fetch the underlying client state.
let (src_chain_client_state, _) = src_chain.query_client_state(
QueryClientStateRequest {
client_id: conn_end.client_id().clone(),
height: QueryHeight::Latest,
},
IncludeProof::No,
)?;

debug!(
"client state underlying the channel: {:?}",
src_chain_client_state
);

// Check that this client is verifying headers for the destination chain.
if &src_chain_client_state.chain_id() != dst_chain_id {
return Err(eyre!(
"the requested port/channel ('{}'/'{}') provides a path from chain '{}' to \
chain '{}' (not to the destination chain '{}'). Bailing due to mismatching arguments.",
src_port_id,
src_channel_id,
src_chain.id(),
src_chain_client_state.chain_id(),
dst_chain_id
));
}

Ok(())
}
1 change: 1 addition & 0 deletions crates/relayer-cli/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ impl Configurable<Config> for CliCmd {

match self {
CliCmd::Tx(cmd) => cmd.override_config(config),
CliCmd::Fee(cmd) => cmd.override_config(config),
// CliCmd::Help(cmd) => cmd.override_config(config),
// CliCmd::Keys(cmd) => cmd.override_config(config),
// CliCmd::Create(cmd) => cmd.override_config(config),
Expand Down
22 changes: 19 additions & 3 deletions crates/relayer-cli/src/commands/fee.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@
//! `fee` subcommand

use abscissa_core::clap::Parser;
use abscissa_core::{Command, Runnable};
use abscissa_core::{config::Override, Command, Runnable};
use ibc_relayer::config::Config;

use register_counterparty_payee::RegisterCounterpartyPayeeCmd;
use register_payee::RegisterPayeeCmd;
use self::register_counterparty_payee::RegisterCounterpartyPayeeCmd;
use self::register_payee::RegisterPayeeCmd;
use self::transfer::FeeTransferCmd;

pub mod register_counterparty_payee;
pub mod register_payee;
pub mod transfer;

#[allow(clippy::large_enum_variant)]
#[derive(Command, Debug, Parser, Runnable)]
pub enum FeeCmd {
/// Register a payee for a channel
RegisterPayee(RegisterPayeeCmd),

/// Register a counterparty payee for a channel
RegisterCounterpartyPayee(RegisterCounterpartyPayeeCmd),

/// Perform a token transfer supported with a fee
Transfer(FeeTransferCmd),
}

impl Override<Config> for FeeCmd {
fn override_config(&self, config: Config) -> Result<Config, abscissa_core::FrameworkError> {
match self {
Self::Transfer(cmd) => cmd.override_config(config),
_ => Ok(config),
}
}
}
Loading