Skip to content

Commit

Permalink
Merge branch 'yuji/ibc-rate-limit' (#2698)
Browse files Browse the repository at this point in the history
* origin/yuji/ibc-rate-limit:
  fix bench
  add calc_throughput
  fix tests
  fix checking burned NFT
  fix tests
  fix limits
  record mint amount
  add ibc params
  check rate limits

# Conflicts:
#	.github/workflows/scripts/e2e.json
#	crates/tests/src/e2e/ibc_tests.rs
  • Loading branch information
tzemanovic committed Apr 11, 2024
2 parents e19f200 + 15b6543 commit 8bef12f
Show file tree
Hide file tree
Showing 22 changed files with 820 additions and 118 deletions.
2 changes: 2 additions & 0 deletions .changelog/unreleased/features/2552-ibc-rate-limit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- IBC rate limit for deposits into and withdrawals out of Namada
([\#2552](https://github.com/anoma/namada/issues/2552))
3 changes: 2 additions & 1 deletion .github/workflows/scripts/e2e.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"e2e::ibc_tests::run_ledger_ibc_with_hermes": 130,
"e2e::ibc_tests::pgf_over_ibc_with_hermes": 240,
"e2e::ibc_tests::proposal_ibc_token_inflation": 600,
"e2e::ibc_tests::ibc_rate_limit": 500,
"e2e::eth_bridge_tests::test_add_to_bridge_pool": 10,
"e2e::ledger_tests::double_signing_gets_slashed": 12,
"e2e::ledger_tests::invalid_transactions": 13,
Expand Down Expand Up @@ -38,4 +39,4 @@
"e2e::wallet_tests::wallet_encrypted_key_cmds": 1,
"e2e::wallet_tests::wallet_encrypted_key_cmds_env_var": 1,
"e2e::wallet_tests::wallet_unencrypted_key_cmds": 1
}
}
2 changes: 1 addition & 1 deletion .github/workflows/scripts/hermes.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.7.4-namada-beta7
1.7.4-namada-beta8-rc
17 changes: 16 additions & 1 deletion crates/apps/src/lib/bench_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ use namada::ibc::core::host::types::path::{
};
use namada::ibc::primitives::proto::{Any, Protobuf};
use namada::ibc::primitives::Timestamp as IbcTimestamp;
use namada::ibc::storage::port_key;
use namada::ibc::storage::{mint_limit_key, port_key, throughput_limit_key};
use namada::ibc::MsgTransfer;
use namada::io::StdIo;
use namada::ledger::dry_run_tx;
Expand Down Expand Up @@ -546,6 +546,21 @@ impl BenchShell {
.unwrap();
}

pub fn enable_ibc_transfer(&mut self) {
let token = address::testing::nam();
let mint_limit_key = mint_limit_key(&token);
self.state
.db_write(&mint_limit_key, Amount::max_signed().serialize_to_vec())
.unwrap();
let throughput_limit_key = throughput_limit_key(&token);
self.state
.db_write(
&throughput_limit_key,
Amount::max_signed().serialize_to_vec(),
)
.unwrap();
}

// Update the block height in state to guarantee a valid response to the
// client queries
pub fn commit_block(&mut self) {
Expand Down
14 changes: 14 additions & 0 deletions crates/apps/src/lib/config/genesis/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,17 @@ impl Finalized {
}
}

pub fn get_ibc_params(&self) -> namada::ibc::parameters::IbcParameters {
let templates::IbcParams {
default_mint_limit,
default_per_epoch_throughput_limit,
} = self.parameters.ibc_params.clone();
namada::ibc::parameters::IbcParameters {
default_mint_limit,
default_per_epoch_throughput_limit,
}
}

pub fn get_token_address(&self, alias: &Alias) -> Option<&Address> {
self.tokens.token.get(alias).map(|token| &token.address)
}
Expand Down Expand Up @@ -713,6 +724,7 @@ pub struct FinalizedParameters {
pub gov_params: templates::GovernanceParams,
pub pgf_params: namada::governance::pgf::parameters::PgfParameters,
pub eth_bridge_params: Option<templates::EthBridgeParams>,
pub ibc_params: templates::IbcParams,
}

impl FinalizedParameters {
Expand All @@ -723,6 +735,7 @@ impl FinalizedParameters {
gov_params,
pgf_params,
eth_bridge_params,
ibc_params,
}: templates::Parameters<Validated>,
) -> Self {
use namada::governance::pgf::parameters::PgfParameters;
Expand All @@ -737,6 +750,7 @@ impl FinalizedParameters {
gov_params,
pgf_params: finalized_pgf_params,
eth_bridge_params,
ibc_params,
}
}
}
Expand Down
20 changes: 20 additions & 0 deletions crates/apps/src/lib/config/genesis/templates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ pub struct Parameters<T: TemplateValidation> {
pub gov_params: GovernanceParams,
pub pgf_params: PgfParams<T>,
pub eth_bridge_params: Option<EthBridgeParams>,
pub ibc_params: IbcParams,
}

#[derive(
Expand Down Expand Up @@ -500,6 +501,23 @@ pub struct EthBridgeParams {
pub contracts: Contracts,
}

#[derive(
Clone,
Debug,
Deserialize,
Serialize,
BorshDeserialize,
BorshSerialize,
PartialEq,
Eq,
)]
pub struct IbcParams {
/// Default supply limit of each token
pub default_mint_limit: token::Amount,
/// Default per-epoch throughput limit of each token
pub default_per_epoch_throughput_limit: token::Amount,
}

impl TokenBalances {
pub fn get(&self, addr: &GenesisAddress) -> Option<token::Amount> {
self.0.get(addr).map(|amt| amt.amount())
Expand Down Expand Up @@ -873,6 +891,7 @@ pub fn validate_parameters(
gov_params,
pgf_params,
eth_bridge_params,
ibc_params,
} = parameters;
match parameters.denominate(tokens) {
Err(e) => {
Expand All @@ -890,6 +909,7 @@ pub fn validate_parameters(
valid: Default::default(),
},
eth_bridge_params,
ibc_params,
}),
}
}
Expand Down
3 changes: 3 additions & 0 deletions crates/apps/src/lib/node/ledger/shell/finalize_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use namada::core::storage::{BlockHash, BlockResults, Epoch, Header};
use namada::governance::pgf::inflation as pgf_inflation;
use namada::hash::Hash;
use namada::ledger::gas::GasMetering;
use namada::ledger::ibc;
use namada::ledger::pos::namada_proof_of_stake;
use namada::ledger::protocol::WrapperArgs;
use namada::proof_of_stake;
Expand Down Expand Up @@ -114,6 +115,8 @@ where
votes,
req.byzantine_validators,
)?;
// - IBC
ibc::finalize_block(&mut self.state, emit_events, new_epoch)?;

if new_epoch {
// Apply PoS and PGF inflation
Expand Down
4 changes: 4 additions & 0 deletions crates/apps/src/lib/node/ledger/shell/init_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,10 @@ where
.unwrap();
}

// Initialize IBC parameters
let ibc_params = genesis.get_ibc_params();
ibc_params.init_storage(&mut self.state).unwrap();

// Depends on parameters being initialized
self.state
.in_mem_mut()
Expand Down
5 changes: 4 additions & 1 deletion crates/benches/native_vps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,10 @@ fn ibc(c: &mut Criterion) {
"open_channel" => {
let _ = shell.init_ibc_connection();
}
"outgoing_transfer" => shell.init_ibc_channel(),
"outgoing_transfer" => {
shell.init_ibc_channel();
shell.enable_ibc_transfer();
}
_ => panic!("Unexpected bench test"),
}

Expand Down
44 changes: 44 additions & 0 deletions crates/ibc/src/context/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,4 +721,48 @@ pub trait IbcCommonContext: IbcStorageContext {
let amount = self.read::<Amount>(&balance_key)?;
Ok(amount == Some(Amount::from_u64(1)))
}

/// Read the mint amount of the given token
fn mint_amount(&self, token: &Address) -> Result<Amount> {
let key = storage::mint_amount_key(token);
Ok(self.read::<Amount>(&key)?.unwrap_or_default())
}

/// Write the mint amount of the given token
fn store_mint_amount(
&mut self,
token: &Address,
amount: Amount,
) -> Result<()> {
let key = storage::mint_amount_key(token);
self.write(&key, amount).map_err(ContextError::from)
}

/// Read the per-epoch deposit of the given token
fn deposit(&self, token: &Address) -> Result<Amount> {
let key = storage::deposit_key(token);
Ok(self.read::<Amount>(&key)?.unwrap_or_default())
}

/// Write the per-epoch deposit of the given token
fn store_deposit(&mut self, token: &Address, amount: Amount) -> Result<()> {
let key = storage::deposit_key(token);
self.write(&key, amount).map_err(ContextError::from)
}

/// Read the per-epoch withdraw of the given token
fn withdraw(&self, token: &Address) -> Result<Amount> {
let key = storage::withdraw_key(token);
Ok(self.read::<Amount>(&key)?.unwrap_or_default())
}

/// Write the per-epoch withdraw of the given token
fn store_withdraw(
&mut self,
token: &Address,
amount: Amount,
) -> Result<()> {
let key = storage::withdraw_key(token);
self.write(&key, amount).map_err(ContextError::from)
}
}
62 changes: 62 additions & 0 deletions crates/ibc/src/context/nft_transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,58 @@ where
pub fn new(inner: Rc<RefCell<C>>) -> Self {
Self { inner }
}

/// Update the mint amount of the token
fn update_mint_amount(
&self,
token: &Address,
is_minted: bool,
) -> Result<(), NftTransferError> {
let mint = self.inner.borrow().mint_amount(token)?;
let updated_mint = if is_minted && mint.is_zero() {
Amount::from_u64(1)
} else if !is_minted && mint == Amount::from_u64(1) {
Amount::zero()
} else {
return Err(NftTransferError::Other(
"The mint amount was invalid".to_string(),
));
};
self.inner
.borrow_mut()
.store_mint_amount(token, updated_mint)
.map_err(NftTransferError::from)
}

/// Add the amount to the per-epoch withdraw of the token
fn add_deposit(&self, token: &Address) -> Result<(), NftTransferError> {
let deposit = self.inner.borrow().deposit(token)?;
let added_deposit =
deposit.checked_add(Amount::from_u64(1)).ok_or_else(|| {
NftTransferError::Other(
"The per-epoch deposit overflowed".to_string(),
)
})?;
self.inner
.borrow_mut()
.store_deposit(token, added_deposit)
.map_err(NftTransferError::from)
}

/// Add the amount to the per-epoch withdraw of the token
fn add_withdraw(&self, token: &Address) -> Result<(), NftTransferError> {
let withdraw = self.inner.borrow().withdraw(token)?;
let added_withdraw =
withdraw.checked_add(Amount::from_u64(1)).ok_or_else(|| {
NftTransferError::Other(
"The per-epoch withdraw overflowed".to_string(),
)
})?;
self.inner
.borrow_mut()
.store_withdraw(token, added_withdraw)
.map_err(NftTransferError::from)
}
}

impl<C> NftTransferValidationContext for NftTransferContext<C>
Expand Down Expand Up @@ -231,6 +283,8 @@ where
) -> Result<(), NftTransferError> {
let ibc_token = storage::ibc_token_for_nft(class_id, token_id);

self.add_withdraw(&ibc_token)?;

self.inner
.borrow_mut()
.transfer_token(
Expand All @@ -253,6 +307,8 @@ where
) -> Result<(), NftTransferError> {
let ibc_token = storage::ibc_token_for_nft(class_id, token_id);

self.add_deposit(&ibc_token)?;

self.inner
.borrow_mut()
.transfer_token(
Expand Down Expand Up @@ -283,6 +339,9 @@ where
};
self.inner.borrow_mut().store_nft_metadata(metadata)?;

self.update_mint_amount(&ibc_token, true)?;
self.add_deposit(&ibc_token)?;

self.inner
.borrow_mut()
.mint_token(account, &ibc_token, Amount::from_u64(1))
Expand All @@ -298,6 +357,9 @@ where
) -> Result<(), NftTransferError> {
let ibc_token = storage::ibc_token_for_nft(class_id, token_id);

self.update_mint_amount(&ibc_token, false)?;
self.add_withdraw(&ibc_token)?;

self.inner
.borrow_mut()
.burn_token(account, &ibc_token, Amount::from_u64(1))
Expand Down
Loading

0 comments on commit 8bef12f

Please sign in to comment.