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

IBC rate limit query #4246

Merged
merged 11 commits into from
Jan 22, 2025
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Added the possibility to query the IBC rate limit of a specified token.
([\#4246](https://github.com/anoma/namada/pull/4246))
54 changes: 54 additions & 0 deletions crates/apps_lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ pub mod cmds {
.subcommand(QuerySlashes::def().display_order(5))
.subcommand(QueryDelegations::def().display_order(5))
.subcommand(QueryFindValidator::def().display_order(5))
.subcommand(QueryIbcRateLimit::def().display_order(5))
.subcommand(QueryResult::def().display_order(5))
.subcommand(QueryRawBytes::def().display_order(5))
.subcommand(QueryProposal::def().display_order(5))
Expand Down Expand Up @@ -397,6 +398,8 @@ pub mod cmds {
let query_commission =
Self::parse_with_ctx(matches, QueryCommissionRate);
let query_metadata = Self::parse_with_ctx(matches, QueryMetaData);
let query_ibc_rate_limit =
Self::parse_with_ctx(matches, QueryIbcRateLimit);
let add_to_eth_bridge_pool =
Self::parse_with_ctx(matches, AddToEthBridgePool);
let shielded_sync = Self::parse_with_ctx(matches, ShieldedSync);
Expand Down Expand Up @@ -459,6 +462,7 @@ pub mod cmds {
.or(query_native_supply)
.or(query_staking_rewards_rate)
.or(query_account)
.or(query_ibc_rate_limit)
.or(shielded_sync)
.or(gen_ibc_shielding)
.or(utils)
Expand Down Expand Up @@ -554,6 +558,7 @@ pub mod cmds {
QueryPgf(QueryPgf),
QueryValidatorState(QueryValidatorState),
QueryRewards(QueryRewards),
QueryIbcRateLimit(QueryIbcRateLimit),
ShieldedSync(ShieldedSync),
GenIbcShieldingTransfer(GenIbcShieldingTransfer),
}
Expand Down Expand Up @@ -2186,6 +2191,27 @@ pub mod cmds {
}
}

#[derive(Clone, Debug)]
pub struct QueryIbcRateLimit(pub args::QueryIbcRateLimit<args::CliTypes>);

impl SubCmd for QueryIbcRateLimit {
const CMD: &'static str = "query-ibc-rate-limits";

fn parse(matches: &ArgMatches) -> Option<Self> {
matches.subcommand_matches(Self::CMD).map(|matches| {
QueryIbcRateLimit(args::QueryIbcRateLimit::parse(matches))
})
}

fn def() -> App {
App::new(Self::CMD)
.about(wrap!(
"Query the IBC rate limit for the provided token."
))
.add_args::<args::QueryIbcRateLimit<args::CliTypes>>()
}
}

#[derive(Clone, Debug)]
pub struct QueryRawBytes(pub args::QueryRawBytes<args::CliTypes>);

Expand Down Expand Up @@ -7472,6 +7498,34 @@ pub mod args {
}
}

impl Args for QueryIbcRateLimit<CliTypes> {
fn parse(matches: &ArgMatches) -> Self {
let query = Query::parse(matches);
let token = TOKEN.parse(matches);

Self { query, token }
}

fn def(app: App) -> App {
app.add_args::<Query<CliTypes>>()
.arg(TOKEN.def().help(wrap!("The IBC token.")))
}
}

impl CliToSdk<QueryIbcRateLimit<SdkTypes>> for QueryIbcRateLimit<CliTypes> {
type Error = std::convert::Infallible;

fn to_sdk(
self,
ctx: &mut Context,
) -> Result<QueryIbcRateLimit<SdkTypes>, Self::Error> {
Ok(QueryIbcRateLimit::<SdkTypes> {
query: self.query.to_sdk(ctx)?,
token: ctx.borrow_chain_or_exit().get(&self.token),
})
}
}

impl CliToSdk<QueryRawBytes<SdkTypes>> for QueryRawBytes<CliTypes> {
type Error = std::convert::Infallible;

Expand Down
12 changes: 12 additions & 0 deletions crates/apps_lib/src/cli/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,18 @@ impl CliApi {
let namada = ctx.to_sdk(client, io);
rpc::query_account(&namada, args).await;
}
Sub::QueryIbcRateLimit(QueryIbcRateLimit(args)) => {
let chain_ctx = ctx.borrow_mut_chain_or_exit();
let ledger_address =
chain_ctx.get(&args.query.ledger_address);
let client = client.unwrap_or_else(|| {
C::from_tendermint_address(&ledger_address)
});
client.wait_until_node_is_synced(&io).await?;
let args = args.to_sdk(&mut ctx)?;
let namada = ctx.to_sdk(client, io);
rpc::query_ibc_rate_limits(&namada, args).await;
}
}
}
cli::NamadaClient::WithoutContext(cmd_box) => {
Expand Down
66 changes: 60 additions & 6 deletions crates/apps_lib/src/client/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use namada_sdk::governance::storage::proposal::{
use namada_sdk::governance::utils::{ProposalVotes, VotePower};
use namada_sdk::governance::ProposalVote;
use namada_sdk::hash::Hash;
use namada_sdk::ibc::parameters::{IbcParameters, IbcTokenRateLimits};
use namada_sdk::io::{display, display_line, edisplay_line, Client, Io};
use namada_sdk::key::*;
use namada_sdk::masp::shielded_wallet::ShieldedApi;
Expand All @@ -46,7 +47,7 @@ use namada_sdk::proof_of_stake::{self, OwnedPosParams, PosParams};
use namada_sdk::queries::RPC;
use namada_sdk::rpc::{
self, enriched_bonds_and_unbonds, format_denominated_amount, query_epoch,
TxResponse,
query_ibc_params, TxResponse,
};
use namada_sdk::state::LastBlock;
use namada_sdk::storage::BlockResults;
Expand Down Expand Up @@ -263,7 +264,7 @@ async fn query_transparent_balance(
.address()
.expect("Balance owner should have been a transparent address");

let token_alias = lookup_token_alias(context, &token, &owner).await;
let token_alias = lookup_token_alias(context, &token, Some(&owner)).await;
let token_balance_result = namada_sdk::rpc::get_token_balance(
context.client(),
&token,
Expand All @@ -290,16 +291,15 @@ async fn query_transparent_balance(
async fn lookup_token_alias(
context: &impl Namada,
token: &Address,
owner: &Address,
owner: Option<&Address>,
) -> String {
match token {
Address::Internal(InternalAddress::Erc20(eth_addr)) => {
eth_addr.to_canonical()
}
Address::Internal(InternalAddress::IbcToken(_)) => {
let ibc_denom =
rpc::query_ibc_denom(context, token.to_string(), Some(owner))
.await;
rpc::query_ibc_denom(context, token.to_string(), owner).await;

context.wallet().await.lookup_ibc_token_alias(ibc_denom)
}
Expand Down Expand Up @@ -499,7 +499,7 @@ async fn query_shielded_balance(
let masp_epoch = query_and_print_masp_epoch(context).await;

// Query the token alias in the wallet for pretty printing token balances
let token_alias = lookup_token_alias(context, &token, &MASP).await;
let token_alias = lookup_token_alias(context, &token, Some(&MASP)).await;

// Query the multi-asset balance at the given spending key
let mut shielded = context.shielded_mut().await;
Expand Down Expand Up @@ -1089,6 +1089,24 @@ pub async fn query_protocol_parameters(
"",
tm_votes_per_token
);

display_line!(context.io(), "\nIBC parameters");
let IbcParameters {
default_rate_limits:
IbcTokenRateLimits {
mint_limit,
throughput_per_epoch_limit,
},
} = query_ibc_params(context.client())
.await
.expect("Failed to query the IBC parameters");
display_line!(context.io(), "{:4}Default mint limit: {}", "", mint_limit);
display_line!(
context.io(),
"{:4}Default per epoch throughput limit: {}",
"",
throughput_per_epoch_limit
);
}

pub async fn query_bond<C: Client + Sync>(
Expand Down Expand Up @@ -2446,3 +2464,39 @@ pub async fn compute_proposal_votes<C: Client + Sync>(
delegator_voting_power,
}
}

/// Query and display the IBC rate limit for the provided token
pub async fn query_ibc_rate_limits(
context: &impl Namada,
args: args::QueryIbcRateLimit,
) {
let token_alias = lookup_token_alias(context, &args.token, None).await;
let native_token = context.native_token();

let IbcTokenRateLimits {
mint_limit,
throughput_per_epoch_limit,
} = unwrap_sdk_result(
rpc::query_ibc_rate_limits(context.client(), &args.token).await,
);

let (mint_str, throughput_str) = if args.token == native_token {
(
mint_limit.to_string_native(),
throughput_per_epoch_limit.to_string_native(),
)
} else {
(
mint_limit.to_string(),
throughput_per_epoch_limit.to_string(),
)
};
display_line!(
context.io(),
"IBC rate limits for token {}:\nGlobal mint limit: {}\nThroughput \
limit: {} per epoch",
token_alias,
mint_str,
throughput_str
);
}
8 changes: 5 additions & 3 deletions crates/apps_lib/src/config/genesis/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use namada_sdk::chain::{ChainId, ChainIdPrefix};
use namada_sdk::eth_bridge::EthereumBridgeParams;
use namada_sdk::governance::pgf::parameters::PgfParameters;
use namada_sdk::hash::Hash;
use namada_sdk::ibc::parameters::IbcParameters;
use namada_sdk::ibc::parameters::{IbcParameters, IbcTokenRateLimits};
use namada_sdk::key::{common, RefTo};
use namada_sdk::parameters::EpochDuration;
use namada_sdk::time::{DateTimeUtc, DurationNanos, Rfc3339String};
Expand Down Expand Up @@ -485,8 +485,10 @@ impl Finalized {
default_per_epoch_throughput_limit,
} = self.parameters.ibc_params.clone();
IbcParameters {
default_mint_limit,
default_per_epoch_throughput_limit,
default_rate_limits: IbcTokenRateLimits {
mint_limit: default_mint_limit,
throughput_per_epoch_limit: default_per_epoch_throughput_limit,
},
}
}

Expand Down
23 changes: 15 additions & 8 deletions crates/ibc/src/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,27 @@ use namada_core::borsh::{BorshDeserialize, BorshSerialize};
use namada_core::token::Amount;
use namada_state::{Result, StorageWrite};

#[derive(Clone, Debug, BorshSerialize, BorshDeserialize)]
#[derive(Clone, Debug, Default, BorshSerialize, BorshDeserialize)]
/// Governance parameter structure
pub struct IbcParameters {
/// Default supply limit of each token
pub default_mint_limit: Amount,
/// Default per-epoch throughput limit of each token
pub default_per_epoch_throughput_limit: Amount,
/// Default rate limits for IBC tokens
pub default_rate_limits: IbcTokenRateLimits,
}

#[derive(Clone, Debug, BorshSerialize, BorshDeserialize)]
/// IBC rate limits for a token
pub struct IbcTokenRateLimits {
/// Global mint limit for the token
pub mint_limit: Amount,
/// Throughput limit per epoch
pub throughput_per_epoch_limit: Amount,
}

impl Default for IbcParameters {
impl Default for IbcTokenRateLimits {
fn default() -> Self {
Self {
default_mint_limit: Amount::zero(),
default_per_epoch_throughput_limit: Amount::zero(),
mint_limit: Amount::zero(),
throughput_per_epoch_limit: Amount::zero(),
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions crates/ibc/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,10 @@ pub fn get_limits<S: StorageRead>(
.read(&params_key())?
.expect("Parameters should be stored");
(
mint_limit.unwrap_or(params.default_mint_limit),
throughput_limit
.unwrap_or(params.default_per_epoch_throughput_limit),
mint_limit.unwrap_or(params.default_rate_limits.mint_limit),
throughput_limit.unwrap_or(
params.default_rate_limits.throughput_per_epoch_limit,
),
)
}
})
Expand Down
8 changes: 5 additions & 3 deletions crates/ibc/src/vp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ mod tests {
};
use crate::core::router::types::event::ModuleEvent;
use crate::event::IbcEventType;
use crate::parameters::IbcParameters;
use crate::parameters::{IbcParameters, IbcTokenRateLimits};
use crate::primitives::proto::{Any, Protobuf};
use crate::primitives::{Timestamp, ToProto};
use crate::storage::{
Expand Down Expand Up @@ -630,8 +630,10 @@ mod tests {
let gov_params = GovernanceParameters::default();
gov_params.init_storage(&mut state).unwrap();
let ibc_params = IbcParameters {
default_mint_limit: Amount::native_whole(100),
default_per_epoch_throughput_limit: Amount::native_whole(100),
default_rate_limits: IbcTokenRateLimits {
mint_limit: Amount::native_whole(100),
throughput_per_epoch_limit: Amount::native_whole(100),
},
};
ibc_params.init_storage(&mut state).unwrap();
namada_proof_of_stake::test_utils::test_init_genesis::<
Expand Down
9 changes: 9 additions & 0 deletions crates/sdk/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2597,6 +2597,15 @@ pub struct QueryRawBytes<C: NamadaTypes = SdkTypes> {
pub query: Query<C>,
}

/// Query the IBC rate limit for the specified token
#[derive(Clone, Debug)]
pub struct QueryIbcRateLimit<C: NamadaTypes = SdkTypes> {
/// Common query args
pub query: Query<C>,
/// Token address
pub token: C::Address,
}

/// The possible values for the tx expiration
#[derive(Clone, Debug, Default)]
pub enum TxExpiration {
Expand Down
Loading
Loading