Skip to content

Commit

Permalink
ibc: replace token dep with DI
Browse files Browse the repository at this point in the history
  • Loading branch information
tzemanovic committed Jul 26, 2024
1 parent 7be24a7 commit 1c9a658
Show file tree
Hide file tree
Showing 27 changed files with 400 additions and 202 deletions.
26 changes: 14 additions & 12 deletions crates/benches/native_vps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1677,19 +1677,20 @@ fn ibc_vp_validate_action(c: &mut Criterion) {

let exec_ctx = IbcVpContext::new(ibc.ctx.pre());
let ctx = Rc::new(RefCell::new(exec_ctx));
let mut actions = IbcActions::<_, parameters::Store<_>>::new(
ctx.clone(),
verifiers.clone(),
);
let mut actions =
IbcActions::<_, parameters::Store<_>, token::Store<()>>::new(
ctx.clone(),
verifiers.clone(),
);
actions.set_validation_params(ibc.validation_params().unwrap());

let module = TransferModule::new(ctx.clone(), verifiers);
actions.add_transfer_module(module);
let module = NftTransferModule::new(ctx);
let module = NftTransferModule::<_, token::Store<()>>::new(ctx);
actions.add_transfer_module(module);

group.bench_function(bench_name, |b| {
b.iter(|| actions.validate(&tx_data).unwrap())
b.iter(|| actions.validate::<Transfer>(&tx_data).unwrap())
});
}

Expand Down Expand Up @@ -1737,19 +1738,20 @@ fn ibc_vp_execute_action(c: &mut Criterion) {
let exec_ctx = IbcVpContext::new(ibc.ctx.pre());
let ctx = Rc::new(RefCell::new(exec_ctx));

let mut actions = IbcActions::<_, parameters::Store<_>>::new(
ctx.clone(),
verifiers.clone(),
);
let mut actions =
IbcActions::<_, parameters::Store<_>, token::Store<()>>::new(
ctx.clone(),
verifiers.clone(),
);
actions.set_validation_params(ibc.validation_params().unwrap());

let module = TransferModule::new(ctx.clone(), verifiers);
actions.add_transfer_module(module);
let module = NftTransferModule::new(ctx);
let module = NftTransferModule::<_, token::Store<()>>::new(ctx);
actions.add_transfer_module(module);

group.bench_function(bench_name, |b| {
b.iter(|| actions.execute(&tx_data).unwrap())
b.iter(|| actions.execute::<token::Transfer>(&tx_data).unwrap())
});
}

Expand Down
2 changes: 1 addition & 1 deletion crates/ibc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ namada_migrations = {path = "../migrations", optional = true}
namada_state = { path = "../state" }
namada_storage = { path = "../storage" }
namada_systems = { path = "../systems" }
namada_token = { path = "../token" }
namada_tx = { path = "../tx" }
namada_vp = { path = "../vp" }

Expand Down Expand Up @@ -58,6 +57,7 @@ namada_governance = { path = "../governance" }
namada_parameters = { path = "../parameters", features = ["testing"] }
namada_proof_of_stake = { path = "../proof_of_stake", features = ["testing"] }
namada_state = { path = "../state", features = ["testing"] }
namada_token = { path = "../token" }
namada_tx = { path = "../tx", features = ["testing"] }
namada_vm = { path = "../vm", features = ["testing"] }

Expand Down
63 changes: 44 additions & 19 deletions crates/ibc/src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@
use std::cell::RefCell;
use std::collections::BTreeSet;
use std::fmt::Debug;
use std::marker::PhantomData;
use std::rc::Rc;

use borsh::BorshDeserialize;
use ibc::apps::transfer::types::msgs::transfer::MsgTransfer as IbcMsgTransfer;
use ibc::apps::transfer::types::packet::PacketData;
use ibc::apps::transfer::types::PrefixedCoin;
use ibc::core::channel::types::timeout::TimeoutHeight;
use namada_core::address::Address;
use namada_core::borsh::BorshSerializeExt;
use namada_core::borsh::{BorshSerialize, BorshSerializeExt};
use namada_core::ibc::PGFIbcTarget;
use namada_core::tendermint::Time as TmTime;
use namada_core::token::Amount;
Expand All @@ -18,8 +21,7 @@ use namada_state::{
Epochs, ResultExt, State, StorageError, StorageRead, StorageResult,
StorageWrite,
};
use namada_systems::parameters;
use namada_token as token;
use namada_systems::{parameters, trans_token};

use crate::event::IbcEvent;
use crate::{
Expand All @@ -29,11 +31,13 @@ use crate::{

/// IBC protocol context
#[derive(Debug)]
pub struct IbcProtocolContext<'a, S> {
pub struct IbcProtocolContext<'a, S, Token> {
state: &'a mut S,
/// Marker for DI types
_marker: PhantomData<Token>,
}

impl<S> StorageRead for IbcProtocolContext<'_, S>
impl<S, Token> StorageRead for IbcProtocolContext<'_, S, Token>
where
S: State,
{
Expand Down Expand Up @@ -96,7 +100,7 @@ where
}
}

impl<S> StorageWrite for IbcProtocolContext<'_, S>
impl<S, Token> StorageWrite for IbcProtocolContext<'_, S, Token>
where
S: State,
{
Expand All @@ -113,9 +117,13 @@ where
}
}

impl<S> IbcStorageContext for IbcProtocolContext<'_, S>
impl<S, Token> IbcStorageContext for IbcProtocolContext<'_, S, Token>
where
S: State + EmitEvents,
Token: trans_token::Keys
+ trans_token::Read<S>
+ trans_token::Write<S>
+ trans_token::Events<S>,
{
type Storage = Self;

Expand All @@ -141,7 +149,7 @@ where
token: &Address,
amount: Amount,
) -> Result<(), StorageError> {
token::transfer(self.state, token, src, dest, amount)
Token::transfer(self.state, token, src, dest, amount)
}

/// Mint token
Expand All @@ -151,7 +159,9 @@ where
token: &Address,
amount: Amount,
) -> Result<(), StorageError> {
ibc_storage::mint_tokens(self.state, target, token, amount)
ibc_storage::mint_tokens_and_emit_event::<_, Token>(
self.state, target, token, amount,
)
}

/// Burn token
Expand All @@ -161,7 +171,7 @@ where
token: &Address,
amount: Amount,
) -> Result<(), StorageError> {
ibc_storage::burn_tokens(self.state, target, token, amount)
ibc_storage::burn_tokens::<_, Token>(self.state, target, token, amount)
}

fn insert_verifier(
Expand All @@ -176,13 +186,18 @@ where
}
}

impl<S> IbcCommonContext for IbcProtocolContext<'_, S> where
S: State + EmitEvents
impl<S, Token> IbcCommonContext for IbcProtocolContext<'_, S, Token>
where
S: State + EmitEvents,
Token: trans_token::Keys
+ trans_token::Read<S>
+ trans_token::Write<S>
+ trans_token::Events<S>,
{
}

/// Transfer tokens over IBC
pub fn transfer_over_ibc<'a, S, Params>(
pub fn transfer_over_ibc<'a, S, Params, Token, Transfer>(
state: &'a mut S,
token: &Address,
source: &Address,
Expand All @@ -191,8 +206,13 @@ pub fn transfer_over_ibc<'a, S, Params>(
where
S: 'a + State + EmitEvents,
Params: parameters::Read<
<IbcProtocolContext<'a, S> as IbcStorageContext>::Storage,
<IbcProtocolContext<'a, S, Token> as IbcStorageContext>::Storage,
>,
Token: trans_token::Keys
+ trans_token::Write<S>
+ trans_token::Events<S>
+ Debug,
Transfer: BorshSerialize + BorshDeserialize,
{
let token = PrefixedCoin {
denom: token.to_string().parse().expect("invalid token"),
Expand All @@ -204,7 +224,10 @@ where
receiver: target.target.clone().into(),
memo: String::default().into(),
};
let ctx = IbcProtocolContext { state };
let ctx = IbcProtocolContext {
state,
_marker: PhantomData,
};
let min_duration = Params::epoch_duration_parameter(&ctx)?.min_duration;
#[allow(clippy::arithmetic_side_effects)]
let timeout_timestamp = ctx
Expand All @@ -224,7 +247,7 @@ where
timeout_height_on_b: TimeoutHeight::Never,
timeout_timestamp_on_b: timeout_timestamp.into(),
};
let data = MsgTransfer {
let data = MsgTransfer::<Transfer> {
message,
transfer: None,
}
Expand All @@ -233,9 +256,11 @@ where
// Use an empty verifiers set placeholder for validation, this is only
// needed in txs and not protocol
let verifiers = Rc::new(RefCell::new(BTreeSet::<Address>::new()));
let mut actions =
IbcActions::<_, Params>::new(Rc::new(RefCell::new(ctx)), verifiers);
actions.execute(&data).into_storage_result()?;
let mut actions = IbcActions::<_, Params, Token>::new(
Rc::new(RefCell::new(ctx)),
verifiers,
);
actions.execute::<Transfer>(&data).into_storage_result()?;

Ok(())
}
13 changes: 8 additions & 5 deletions crates/ibc/src/context/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ use ibc::primitives::Timestamp;
use namada_core::address::Address;
use namada_core::storage::{BlockHeight, Key};
use namada_core::tendermint::Time as TmTime;
use namada_core::token::Amount;
use namada_state::{StorageError, StorageRead, StorageWrite};
use namada_token::storage_key::balance_key;
use namada_token::Amount;
use namada_systems::trans_token;
use prost::Message;

use super::client::{AnyClientState, AnyConsensusState};
Expand Down Expand Up @@ -689,14 +689,17 @@ pub trait IbcCommonContext: IbcStorageContext {
}

/// Return true if the NFT is owned by the owner
fn is_nft_owned(
fn is_nft_owned<Token>(
&self,
class_id: &PrefixedClassId,
token_id: &TokenId,
owner: &Address,
) -> Result<bool> {
) -> Result<bool>
where
Token: trans_token::Keys,
{
let ibc_token = trace::ibc_token_for_nft(class_id, token_id);
let balance_key = balance_key(&ibc_token, owner);
let balance_key = Token::balance_key(&ibc_token, owner);
let amount = self.storage().read::<Amount>(&balance_key)?;
Ok(amount == Some(Amount::from_u64(1)))
}
Expand Down
33 changes: 21 additions & 12 deletions crates/ibc/src/context/nft_transfer.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! IBC Non-Fungible token transfer context
use std::cell::RefCell;
use std::marker::PhantomData;
use std::rc::Rc;

use ibc::apps::nft_transfer::context::{
Expand All @@ -15,26 +16,32 @@ use ibc::core::handler::types::error::ContextError;
use ibc::core::host::types::identifiers::{ChannelId, PortId};
use namada_core::address::Address;
use namada_core::token::Amount;
use namada_systems::trans_token;

use super::common::IbcCommonContext;
use crate::{trace, NftClass, NftMetadata, IBC_ESCROW_ADDRESS};

/// NFT transfer context to handle tokens
#[derive(Debug)]
pub struct NftTransferContext<C>
pub struct NftTransferContext<C, Token>
where
C: IbcCommonContext,
{
inner: Rc<RefCell<C>>,
_marker: PhantomData<Token>,
}

impl<C> NftTransferContext<C>
impl<C, Token> NftTransferContext<C, Token>
where
C: IbcCommonContext,
Token: trans_token::Keys,
{
/// Make new NFT transfer context
pub fn new(inner: Rc<RefCell<C>>) -> Self {
Self { inner }
Self {
inner,
_marker: PhantomData,
}
}

/// Update the mint amount of the token
Expand Down Expand Up @@ -110,9 +117,10 @@ where
}
}

impl<C> NftTransferValidationContext for NftTransferContext<C>
impl<C, Token> NftTransferValidationContext for NftTransferContext<C, Token>
where
C: IbcCommonContext,
Token: trans_token::Keys,
{
type AccountId = Address;
type Nft = NftMetadata;
Expand Down Expand Up @@ -156,11 +164,11 @@ where
self.get_nft(class_id, token_id)?;

// Check the account owns the NFT
if self
.inner
.borrow()
.is_nft_owned(class_id, token_id, from_account)?
{
if self.inner.borrow().is_nft_owned::<Token>(
class_id,
token_id,
from_account,
)? {
Ok(())
} else {
Err(NftTransferError::Other(format!(
Expand All @@ -183,7 +191,7 @@ where
self.get_nft(class_id, token_id)?;

// Check the NFT is escrowed
if self.inner.borrow().is_nft_owned(
if self.inner.borrow().is_nft_owned::<Token>(
class_id,
token_id,
&IBC_ESCROW_ADDRESS,
Expand Down Expand Up @@ -224,7 +232,7 @@ where
if self
.inner
.borrow()
.is_nft_owned(class_id, token_id, account)?
.is_nft_owned::<Token>(class_id, token_id, account)?
{
Ok(())
} else {
Expand Down Expand Up @@ -270,9 +278,10 @@ where
}
}

impl<C> NftTransferExecutionContext for NftTransferContext<C>
impl<C, Token> NftTransferExecutionContext for NftTransferContext<C, Token>
where
C: IbcCommonContext,
Token: trans_token::Keys,
{
fn create_or_update_class_execute(
&self,
Expand Down
Loading

0 comments on commit 1c9a658

Please sign in to comment.