Skip to content

Commit 82b94e5

Browse files
committed
Adds support for MASP frontend sus fee over IBC
1 parent 9f7d514 commit 82b94e5

File tree

10 files changed

+156
-91
lines changed

10 files changed

+156
-91
lines changed

crates/apps_lib/src/cli.rs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5229,7 +5229,13 @@ pub mod args {
52295229
ibc_memo: self.ibc_memo,
52305230
gas_spending_key,
52315231
tx_code_path: self.tx_code_path.to_path_buf(),
5232-
frontend_sus_fee: None,
5232+
frontend_sus_fee: self.frontend_sus_fee.map(|fee| {
5233+
TxTransparentTarget {
5234+
target: chain_ctx.get(&fee.target),
5235+
token: chain_ctx.get(&fee.token),
5236+
amount: fee.amount,
5237+
}
5238+
}),
52335239
})
52345240
}
52355241
}
@@ -5258,8 +5264,6 @@ pub mod args {
52585264
let ibc_memo = IBC_MEMO.parse(matches);
52595265
let gas_spending_key = GAS_SPENDING_KEY.parse(matches);
52605266
let tx_code_path = PathBuf::from(TX_IBC_WASM);
5261-
// FIXME: this api is to confusing, split the amount into two,
5262-
// source amount and target amount
52635267
#[cfg(any(test, feature = "testing"))]
52645268
let frontend_sus_fee =
52655269
FRONTEND_SUS_FEE.parse(matches).map(|target|
@@ -5278,8 +5282,6 @@ pub mod args {
52785282
#[cfg(not(any(test, feature = "testing")))]
52795283
let frontend_sus_fee = None;
52805284

5281-
eprintln!("AMOUNT IN CLI: {:#?}", amount); //FIXME: remove
5282-
52835285
Self {
52845286
tx,
52855287
source,
@@ -5290,7 +5292,6 @@ pub mod args {
52905292
channel_id,
52915293
timeout_height,
52925294
timeout_sec_offset,
5293-
// FIXME: check this refund, we should not refund the fee
52945295
refund_target,
52955296
ibc_shielding_data,
52965297
ibc_memo,
@@ -5301,7 +5302,8 @@ pub mod args {
53015302
}
53025303

53035304
fn def(app: App) -> App {
5304-
app.add_args::<Tx<CliTypes>>()
5305+
let app = app
5306+
.add_args::<Tx<CliTypes>>()
53055307
.arg(SOURCE.def().help(wrap!(
53065308
"The source account address. The source's key is used to \
53075309
produce the signature."
@@ -5345,7 +5347,15 @@ pub mod args {
53455347
"The optional spending key that will be used for gas \
53465348
payment (if this is a shielded action). When not \
53475349
provided the source spending key will be used."
5348-
)))
5350+
)));
5351+
5352+
#[cfg(any(test, feature = "testing"))]
5353+
let app = app.arg(FRONTEND_SUS_FEE.def().help(wrap!(
5354+
"The optional address of the frontend provider that will take \
5355+
the masp sustainability fee."
5356+
)));
5357+
5358+
app
53495359
}
53505360
}
53515361

@@ -7389,14 +7399,11 @@ pub mod args {
73897399
None => TxExpiration::Default,
73907400
}
73917401
};
7392-
// FIXME: this api is to confusing, split the amount into two,
7393-
// source amount and target amount
73947402
#[cfg(any(test, feature = "testing"))]
73957403
let frontend_sus_fee = FRONTEND_SUS_FEE_IBC.parse(matches).map(
73967404
|target| // Take a constant fee of 1 on top of the input amount
73977405
(
73987406
target,
7399-
//FIXME: this means we can't do anything when it comes to nfts for this frontend fee
74007407
InputAmount::Unvalidated(
74017408
token::DenominatedAmount::new(
74027409
1.into(),
@@ -7409,8 +7416,6 @@ pub mod args {
74097416
#[cfg(not(any(test, feature = "testing")))]
74107417
let frontend_sus_fee = None;
74117418

7412-
eprintln!("AMOUNT IN CLI: {:#?}", amount); //FIXME: remove
7413-
74147419
Self {
74157420
query,
74167421
output_folder,

crates/apps_lib/src/client/tx.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2011,17 +2011,18 @@ pub async fn gen_ibc_shielding_transfer(
20112011
) -> Result<(), error::Error> {
20122012
let output_folder = args.output_folder.clone();
20132013

2014-
if let Some(masp_tx) = tx::gen_ibc_shielding_transfer(context, args).await?
2014+
if let Some(shielding_data) =
2015+
tx::gen_ibc_shielding_transfer(context, args).await?
20152016
{
2016-
let tx_id = masp_tx.txid().to_string();
2017+
let tx_id = shielding_data.0.txid().to_string();
20172018
let filename = format!("ibc_masp_tx_{}.memo", tx_id);
20182019
let output_path = match output_folder {
20192020
Some(path) => path.join(filename),
20202021
None => filename.into(),
20212022
};
20222023
let mut out = File::create(&output_path)
20232024
.expect("Creating a new file for IBC MASP transaction failed.");
2024-
let bytes = convert_masp_tx_to_ibc_memo(&masp_tx);
2025+
let bytes = convert_masp_tx_to_ibc_memo(shielding_data);
20252026
out.write_all(bytes.as_bytes())
20262027
.expect("Writing IBC MASP transaction file failed.");
20272028
println!(

crates/ibc/src/lib.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -239,11 +239,13 @@ where
239239
{
240240
fn try_extract_masp_tx_from_envelope<Transfer: BorshDeserialize>(
241241
tx_data: &[u8],
242-
) -> StorageResult<Option<masp_primitives::transaction::Transaction>> {
242+
) -> StorageResult<
243+
Option<(masp_primitives::transaction::Transaction, Option<Address>)>,
244+
> {
243245
let msg = decode_message::<Transfer>(tx_data)
244246
.into_storage_result()
245247
.ok();
246-
let tx = if let Some(IbcMessage::Envelope(envelope)) = msg {
248+
let data = if let Some(IbcMessage::Envelope(envelope)) = msg {
247249
Some(extract_masp_tx_from_envelope(&envelope).ok_or_else(|| {
248250
StorageError::new_const(
249251
"Missing MASP transaction in IBC message",
@@ -252,7 +254,7 @@ where
252254
} else {
253255
None
254256
};
255-
Ok(tx)
257+
Ok(data.map(|shielding_data| (shielding_data.0, shielding_data.1)))
256258
}
257259

258260
fn apply_ibc_packet<Transfer: BorshDeserialize>(
@@ -576,9 +578,10 @@ where
576578
#[derive(Debug)]
577579
pub struct InternalData<Transfer> {
578580
/// The transparent transfer that happens in parallel to IBC processes
581+
// FIXME: can't we use this to encode the masp fee payment?
579582
pub transparent: Option<Transfer>,
580583
/// The shielded transaction that happens in parallel to IBC processes
581-
pub shielded: Option<MaspTransaction>,
584+
pub shielded: Option<(MaspTransaction, Option<Address>)>,
582585
/// IBC tokens that are credited/debited to internal accounts
583586
pub ibc_tokens: BTreeSet<Address>,
584587
}
@@ -737,7 +740,7 @@ where
737740
.map_err(|e| Error::Handler(Box::new(e)))?;
738741

739742
// Extract MASP tx from the memo in the packet if needed
740-
let (masp_tx, tokens) = match &*envelope {
743+
let (shielding_data, tokens) = match &*envelope {
741744
MsgEnvelope::Packet(PacketMsg::Recv(msg))
742745
if self
743746
.is_receiving_success(msg)?
@@ -773,7 +776,7 @@ where
773776
};
774777
Ok(InternalData {
775778
transparent: None,
776-
shielded: masp_tx,
779+
shielded: shielding_data.map(|data| (data.0, data.1)),
777780
ibc_tokens: tokens,
778781
})
779782
}

crates/ibc/src/msg.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,10 @@ impl<Transfer: BorshSchema> BorshSchema for MsgNftTransfer<Transfer> {
238238

239239
/// Shielding data in IBC packet memo
240240
#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)]
241-
pub struct IbcShieldingData(pub MaspTransaction);
241+
pub struct IbcShieldingData(
242+
pub MaspTransaction,
243+
pub Option<namada_vp::Address>,
244+
);
242245

243246
impl From<&IbcShieldingData> for String {
244247
fn from(data: &IbcShieldingData) -> Self {
@@ -272,7 +275,7 @@ impl FromStr for IbcShieldingData {
272275
/// Extract MASP transaction from IBC envelope
273276
pub fn extract_masp_tx_from_envelope(
274277
envelope: &MsgEnvelope,
275-
) -> Option<MaspTransaction> {
278+
) -> Option<IbcShieldingData> {
276279
match envelope {
277280
MsgEnvelope::Packet(PacketMsg::Recv(msg)) => {
278281
extract_masp_tx_from_packet(&msg.packet)
@@ -299,9 +302,11 @@ pub fn decode_ibc_shielding_data(
299302
}
300303

301304
/// Extract MASP transaction from IBC packet memo
302-
pub fn extract_masp_tx_from_packet(packet: &Packet) -> Option<MaspTransaction> {
305+
pub fn extract_masp_tx_from_packet(
306+
packet: &Packet,
307+
) -> Option<IbcShieldingData> {
303308
let memo = extract_memo_from_packet(packet, &packet.port_id_on_b)?;
304-
decode_ibc_shielding_data(memo).map(|data| data.0)
309+
decode_ibc_shielding_data(memo)
305310
}
306311

307312
fn extract_memo_from_packet(
@@ -366,6 +371,8 @@ pub fn extract_traces_from_recv_msg(
366371
}
367372

368373
/// Get IBC memo string from MASP transaction for receiving
369-
pub fn convert_masp_tx_to_ibc_memo(transaction: &MaspTransaction) -> String {
370-
IbcShieldingData(transaction.clone()).into()
374+
pub fn convert_masp_tx_to_ibc_memo(
375+
ibc_shielding_data: IbcShieldingData,
376+
) -> String {
377+
ibc_shielding_data.into()
371378
}

crates/sdk/src/args.rs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -521,12 +521,10 @@ pub enum Slippage {
521521
},
522522
}
523523

524-
// FIXME: do we need a new event for the frontend fee?
525-
// FIXME: should the fee be taken shielded? It might avoid us to update the ibc
526-
// methods actually. Yes but it would produce a substantial amount of notes with
527-
// very little amounts FIXME: what happens to the sus fee if we wanto to
524+
// FIXME: what happens to the sus fee if we wanto to
528525
// shield/unshield more than one asset? It should probably be a vector of
529-
// targets, one for every asset
526+
// targets, one for every asset, yes but only for non-ibc txs, for ibc we only
527+
// support a single asset
530528
/// An token swap on Osmosis
531529
#[derive(Debug, Clone)]
532530
pub struct TxOsmosisSwap<C: NamadaTypes = SdkTypes> {
@@ -748,9 +746,7 @@ impl TxOsmosisSwap<SdkTypes> {
748746
let memo = assert_json_obj(
749747
serde_json::to_value(&NamadaMemo {
750748
namada: NamadaMemoData::OsmosisSwap {
751-
shielding_data: StringEncoded::new(
752-
IbcShieldingData(shielding_tx),
753-
),
749+
shielding_data: StringEncoded::new(shielding_tx),
754750
shielded_amount: amount_to_shield,
755751
overflow_receiver,
756752
},
@@ -830,8 +826,6 @@ pub struct TxIbcTransfer<C: NamadaTypes = SdkTypes> {
830826
/// Refund target address when the shielded transfer failure
831827
pub refund_target: Option<C::TransferTarget>,
832828
/// IBC shielding transfer data for the destination chain
833-
// FIXME: here the shielding transaction to reapply to namada, it should
834-
// carry the sus fee
835829
pub ibc_shielding_data: Option<IbcShieldingData>,
836830
/// Memo for IBC transfer packet
837831
pub ibc_memo: Option<String>,
@@ -841,7 +835,6 @@ pub struct TxIbcTransfer<C: NamadaTypes = SdkTypes> {
841835
// FIXME: this should probably be an either with ibc_shielding_data. Yes
842836
// but there would still be the room for errors, maybe need marker traits?
843837
// Not sure...
844-
// FIXME: support this in the client for testing only
845838
pub frontend_sus_fee: Option<TxTransparentTarget<C>>,
846839
/// Path to the TX WASM code file
847840
pub tx_code_path: PathBuf,

crates/sdk/src/masp.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ fn extract_masp_tx(
8383

8484
if let Some(transaction) = extract_masp_tx_from_envelope(&envelope)
8585
{
86-
Ok(transaction)
86+
Ok(transaction.0)
8787
} else {
8888
Err(Error::Other(
8989
"Failed to retrieve MASP over IBC transaction".to_string(),

crates/sdk/src/tx.rs

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use std::time::Duration;
88

99
use borsh::BorshSerialize;
1010
use masp_primitives::asset_type::AssetType;
11-
use masp_primitives::transaction::Transaction as MaspTransaction;
1211
use masp_primitives::transaction::builder::Builder;
1312
use masp_primitives::transaction::components::I128Sum;
1413
use masp_primitives::transaction::components::sapling::builder::{
@@ -55,7 +54,7 @@ use namada_governance::storage::proposal::{
5554
use namada_governance::storage::vote::ProposalVote;
5655
use namada_ibc::storage::channel_key;
5756
use namada_ibc::trace::is_nft_trace;
58-
use namada_ibc::{MsgNftTransfer, MsgTransfer};
57+
use namada_ibc::{IbcShieldingData, MsgNftTransfer, MsgTransfer};
5958
use namada_io::{Client, Io, display_line, edisplay_line};
6059
use namada_proof_of_stake::parameters::{
6160
MAX_VALIDATOR_METADATA_LEN, PosParams,
@@ -2827,7 +2826,6 @@ pub async fn build_ibc_transfer(
28272826
masp_fee_data
28282827
};
28292828

2830-
// FIXME: adjust this
28312829
if let Some(TxTransparentTarget {
28322830
target,
28332831
token,
@@ -2844,14 +2842,20 @@ pub async fn build_ibc_transfer(
28442842
args.tx.force,
28452843
)
28462844
.await?;
2845+
masp_transfer_data.sources.push((
2846+
args.source.clone(),
2847+
args.token.clone(),
2848+
validated_amount,
2849+
));
28472850
masp_transfer_data.targets.push((
28482851
TransferTarget::Address(target.to_owned()),
28492852
token.to_owned(),
28502853
validated_amount,
28512854
));
28522855

28532856
transfer = transfer
2854-
.credit(
2857+
.transfer(
2858+
source.to_owned(),
28552859
target.to_owned(),
28562860
token.to_owned(),
28572861
validated_amount,
@@ -4206,7 +4210,7 @@ pub async fn build_custom(
42064210
pub async fn gen_ibc_shielding_transfer<N: Namada>(
42074211
context: &N,
42084212
args: args::GenIbcShieldingTransfer,
4209-
) -> Result<Option<MaspTransaction>> {
4213+
) -> Result<Option<IbcShieldingData>> {
42104214
let source = IBC;
42114215

42124216
let token = match args.asset {
@@ -4247,26 +4251,28 @@ pub async fn gen_ibc_shielding_transfer<N: Namada>(
42474251
.precompute_asset_types(context.client(), tokens)
42484252
.await;
42494253

4250-
let (extra_target, source_amount) = match &args.frontend_sus_fee {
4251-
Some((target, amount)) => {
4252-
// Validate the amount given
4253-
let validated_fee_amount =
4254-
validate_amount(context, amount.to_owned(), &token, false)
4255-
.await?;
4256-
let source_amount =
4257-
checked!(validated_amount + validated_fee_amount)?;
4258-
4259-
(
4260-
vec![(
4261-
target.to_owned(),
4262-
token.to_owned(),
4263-
validated_fee_amount,
4264-
)],
4265-
source_amount,
4266-
)
4267-
}
4268-
None => (vec![], validated_amount),
4269-
};
4254+
let (extra_recipient, extra_target, source_amount) =
4255+
match &args.frontend_sus_fee {
4256+
Some((target, amount)) => {
4257+
// Validate the amount given
4258+
let validated_fee_amount =
4259+
validate_amount(context, amount.to_owned(), &token, false)
4260+
.await?;
4261+
let source_amount =
4262+
checked!(validated_amount + validated_fee_amount)?;
4263+
4264+
(
4265+
target.address(),
4266+
vec![(
4267+
target.to_owned(),
4268+
token.to_owned(),
4269+
validated_fee_amount,
4270+
)],
4271+
source_amount,
4272+
)
4273+
}
4274+
None => (None, vec![], validated_amount),
4275+
};
42704276

42714277
let masp_transfer_data = MaspTransferData {
42724278
sources: vec![(
@@ -4281,9 +4287,6 @@ pub async fn gen_ibc_shielding_transfer<N: Namada>(
42814287
.concat(),
42824288
};
42834289

4284-
// eprintln!("MASP TRANSFER DATA: {:#?}", masp_transfer_data); //FIXME:
4285-
// remove
4286-
42874290
let shielded_transfer = {
42884291
let mut shielded = context.shielded_mut().await;
42894292
shielded
@@ -4299,10 +4302,8 @@ pub async fn gen_ibc_shielding_transfer<N: Namada>(
42994302
.map_err(|err| TxSubmitError::MaspError(err.to_string()))?
43004303
};
43014304

4302-
// eprintln!("GENERATED MASP BUNDLE: {:#?}", shielded_transfer); //FIXME:
4303-
// remove
4304-
4305-
Ok(shielded_transfer.map(|st| st.masp_tx))
4305+
Ok(shielded_transfer
4306+
.map(|st| IbcShieldingData(st.masp_tx, extra_recipient)))
43064307
}
43074308

43084309
pub(crate) async fn get_ibc_src_port_channel(

0 commit comments

Comments
 (0)