Skip to content

Commit

Permalink
Merge branch 'yuji/ibc-shielded-actions' (#1917)
Browse files Browse the repository at this point in the history
* origin/yuji/ibc-shielded-actions:
  fix error handling
  add changelog
  fix get_ibc_event
  remove Address::Foreign
  fix get_shielded_action
  fix after merge
  workaround for decoding asset types for IbcToken
  WIP: add e2e test for receiving to payment address
  add gen_ibc_shielded_transfer
  WIP: receive to a shielded address
  • Loading branch information
tzemanovic committed Oct 24, 2023
2 parents ed3cb64 + af011f6 commit 97c31d3
Show file tree
Hide file tree
Showing 35 changed files with 1,209 additions and 480 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- IBC transfer to a payment address
([\#1917](https://github.com/anoma/namada/issues/1917))
100 changes: 96 additions & 4 deletions apps/src/lib/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ pub mod cmds {
.subcommand(QueryValidatorState::def().display_order(5))
// Actions
.subcommand(SignTx::def().display_order(6))
.subcommand(GenIbcShieldedTransafer::def().display_order(6))
// Utils
.subcommand(Utils::def().display_order(7))
}
Expand Down Expand Up @@ -315,6 +316,8 @@ pub mod cmds {
let add_to_eth_bridge_pool =
Self::parse_with_ctx(matches, AddToEthBridgePool);
let sign_tx = Self::parse_with_ctx(matches, SignTx);
let gen_ibc_shielded =
Self::parse_with_ctx(matches, GenIbcShieldedTransafer);
let utils = SubCmd::parse(matches).map(Self::WithoutContext);
tx_custom
.or(tx_transfer)
Expand Down Expand Up @@ -353,6 +356,7 @@ pub mod cmds {
.or(query_validator_state)
.or(query_account)
.or(sign_tx)
.or(gen_ibc_shielded)
.or(utils)
}
}
Expand Down Expand Up @@ -428,6 +432,7 @@ pub mod cmds {
QueryPgf(QueryPgf),
QueryValidatorState(QueryValidatorState),
SignTx(SignTx),
GenIbcShieldedTransafer(GenIbcShieldedTransafer),
}

#[allow(clippy::large_enum_variant)]
Expand Down Expand Up @@ -1899,6 +1904,29 @@ pub mod cmds {
}
}

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

impl SubCmd for GenIbcShieldedTransafer {
const CMD: &'static str = "ibc-gen-shielded";

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

fn def() -> App {
App::new(Self::CMD)
.about("Generate shielded transfer for IBC.")
.add_args::<args::GenIbcShieldedTransafer<args::CliTypes>>()
}
}

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

Expand Down Expand Up @@ -2688,7 +2716,7 @@ pub mod args {
pub const HD_WALLET_DERIVATION_PATH_OPT: ArgOpt<String> =
HD_WALLET_DERIVATION_PATH.opt();
pub const HISTORIC: ArgFlag = flag("historic");
pub const IBC_TRANSFER_MEMO: ArgOpt<String> = arg_opt("memo");
pub const IBC_TRANSFER_MEMO_PATH: ArgOpt<PathBuf> = arg_opt("memo-path");
pub const LEDGER_ADDRESS_ABOUT: &str =
"Address of a ledger node as \"{scheme}://{host}:{port}\". If the \
scheme is not supplied, it is assumed to be TCP.";
Expand Down Expand Up @@ -2742,6 +2770,7 @@ pub mod args {
pub const SAFE_MODE: ArgFlag = flag("safe-mode");
pub const SCHEME: ArgDefault<SchemeType> =
arg_default("scheme", DefaultFn(|| SchemeType::Ed25519));
pub const SENDER: Arg<String> = arg("sender");
pub const SIGNING_KEYS: ArgMulti<WalletKeypair> = arg_multi("signing-keys");
pub const SIGNATURES: ArgMulti<PathBuf> = arg_multi("signatures");
pub const SOURCE: Arg<WalletAddress> = arg("source");
Expand Down Expand Up @@ -3604,7 +3633,10 @@ pub mod args {
let channel_id = CHANNEL_ID.parse(matches);
let timeout_height = TIMEOUT_HEIGHT.parse(matches);
let timeout_sec_offset = TIMEOUT_SEC_OFFSET.parse(matches);
let memo = IBC_TRANSFER_MEMO.parse(matches);
let memo = IBC_TRANSFER_MEMO_PATH.parse(matches).map(|path| {
std::fs::read_to_string(path)
.expect("Expected a file at given path")
});
let tx_code_path = PathBuf::from(TX_IBC_WASM);
Self {
tx,
Expand Down Expand Up @@ -3641,9 +3673,9 @@ pub mod args {
)
.arg(TIMEOUT_SEC_OFFSET.def().help("The timeout as seconds."))
.arg(
IBC_TRANSFER_MEMO
IBC_TRANSFER_MEMO_PATH
.def()
.help("Memo field of ICS20 transfer."),
.help("The path for the memo field of ICS20 transfer."),
)
}
}
Expand Down Expand Up @@ -4818,6 +4850,66 @@ pub mod args {
}
}

impl CliToSdk<GenIbcShieldedTransafer<SdkTypes>>
for GenIbcShieldedTransafer<CliTypes>
{
fn to_sdk(
self,
ctx: &mut Context,
) -> GenIbcShieldedTransafer<SdkTypes> {
GenIbcShieldedTransafer::<SdkTypes> {
query: self.query.to_sdk(ctx),
output_folder: self.output_folder,
target: ctx.get(&self.target),
token: ctx.get(&self.token),
amount: self.amount,
port_id: self.port_id,
channel_id: self.channel_id,
}
}
}

impl Args for GenIbcShieldedTransafer<CliTypes> {
fn parse(matches: &ArgMatches) -> Self {
let query = Query::parse(matches);
let output_folder = OUTPUT_FOLDER_PATH.parse(matches);
let target = TRANSFER_TARGET.parse(matches);
let token = TOKEN.parse(matches);
let amount = InputAmount::Unvalidated(AMOUNT.parse(matches));
let port_id = PORT_ID.parse(matches);
let channel_id = CHANNEL_ID.parse(matches);
Self {
query,
output_folder,
target,
token,
amount,
port_id,
channel_id,
}
}

fn def(app: App) -> App {
app.add_args::<Query<CliTypes>>()
.arg(OUTPUT_FOLDER_PATH.def().help(
"The output folder path where the artifact will be stored.",
))
.arg(TRANSFER_TARGET.def().help("The target address."))
.arg(TOKEN.def().help("The transfer token."))
.arg(AMOUNT.def().help("The amount to transfer in decimal."))
.arg(
PORT_ID
.def()
.help("The port ID via which the token is received."),
)
.arg(
CHANNEL_ID.def().help(
"The channel ID via which the token is received.",
),
)
}
}

impl CliToSdk<QueryCommissionRate<SdkTypes>> for QueryCommissionRate<CliTypes> {
fn to_sdk(self, ctx: &mut Context) -> QueryCommissionRate<SdkTypes> {
QueryCommissionRate::<SdkTypes> {
Expand Down
13 changes: 13 additions & 0 deletions apps/src/lib/cli/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,19 @@ impl CliApi {
let namada = ctx.to_sdk(&client, io);
tx::sign_tx(&namada, args).await?;
}
Sub::GenIbcShieldedTransafer(GenIbcShieldedTransafer(
mut args,
)) => {
let client = client.unwrap_or_else(|| {
C::from_tendermint_address(
&mut args.query.ledger_address,
)
});
client.wait_until_node_is_synced(io).await?;
let args = args.to_sdk(&mut ctx);
let namada = ctx.to_sdk(&client, io);
tx::gen_ibc_shielded_transfer(&namada, args).await?;
}
}
}
cli::NamadaClient::WithoutContext(cmd, global_args) => match cmd {
Expand Down
29 changes: 29 additions & 0 deletions apps/src/lib/client/tx.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use std::fs::File;
use std::io::Write;

use namada::core::ledger::governance::cli::offline::{
OfflineProposal, OfflineSignedProposal, OfflineVote,
};
use namada::core::ledger::governance::cli::onchain::{
DefaultProposal, PgfFundingProposal, PgfStewardProposal, ProposalVote,
};
use namada::ibc::applications::transfer::Memo;
use namada::proto::Tx;
use namada::types::address::{Address, ImplicitAddress};
use namada::types::dec::Dec;
Expand Down Expand Up @@ -1091,3 +1093,30 @@ pub async fn submit_tx<'a>(
) -> Result<TxResponse, error::Error> {
tx::submit_tx(namada, to_broadcast).await
}

pub async fn gen_ibc_shielded_transfer<'a>(
context: &impl Namada<'a>,
args: args::GenIbcShieldedTransafer,
) -> Result<(), error::Error> {
if let Some(shielded_transfer) =
tx::gen_ibc_shielded_transfer(context, args.clone()).await?
{
let tx_id = shielded_transfer.masp_tx.txid().to_string();
let filename = format!("ibc_shielded_transfer_{}.memo", tx_id);
let output_path = match &args.output_folder {
Some(path) => path.join(filename),
None => filename.into(),
};
let mut out = File::create(&output_path)
.expect("Should be able to create the out file.");
out.write_all(Memo::from(shielded_transfer).as_ref().as_bytes())
.expect("IBC memo should be deserializable.");
println!(
"Output IBC shielded transfer for {tx_id} to {}",
output_path.to_string_lossy()
);
} else {
eprintln!("No shielded transfer for this IBC transfer.")
}
Ok(())
}
49 changes: 8 additions & 41 deletions benches/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,7 @@ use namada::types::time::DateTimeUtc;
use namada::types::token::DenominatedAmount;
use namada::types::transaction::governance::InitProposalData;
use namada::types::transaction::pos::Bond;
use namada::types::transaction::GasLimit;
use namada::vm::wasm::run;
use namada_apps::cli::args::{Tx as TxArgs, TxTransfer};
use namada_apps::cli::context::FromContext;
use namada_apps::cli::Context;
use namada_apps::config::TendermintMode;
Expand All @@ -97,7 +95,6 @@ use namada_apps::facade::tendermint_proto::google::protobuf::Timestamp;
use namada_apps::node::ledger::shell::Shell;
use namada_apps::wallet::{defaults, CliWalletUtils};
use namada_apps::{config, wasm_loader};
use namada_sdk::args::InputAmount;
use namada_sdk::masp::{
self, ShieldedContext, ShieldedTransfer, ShieldedUtils,
};
Expand Down Expand Up @@ -769,44 +766,10 @@ impl BenchShieldedCtx {
source: TransferSource,
target: TransferTarget,
) -> Tx {
let mock_args = TxArgs {
dry_run: false,
dry_run_wrapper: false,
dump_tx: false,
force: false,
broadcast_only: false,
ledger_address: (),
initialized_account_alias: None,
fee_amount: None,
fee_token: address::nam(),
fee_unshield: None,
gas_limit: GasLimit::from(u64::MAX),
expiration: None,
disposable_signing_key: false,
signing_keys: vec![defaults::albert_keypair()],
signatures: vec![],
wallet_alias_force: true,
chain_id: None,
tx_reveal_code_path: TX_REVEAL_PK_WASM.into(),
verification_key: None,
password: None,
wrapper_fee_payer: None,
output_folder: None,
};

let args = TxTransfer {
tx: mock_args,
source: source.clone(),
target: target.clone(),
token: address::nam(),
amount: InputAmount::Validated(DenominatedAmount {
amount,
denom: 0.into(),
}),
native_token: self.shell.wl_storage.storage.native_token.clone(),
tx_code_path: TX_TRANSFER_WASM.into(),
let denominated_amount = DenominatedAmount {
amount,
denom: 0.into(),
};

let async_runtime = tokio::runtime::Runtime::new().unwrap();
let spending_key = self
.wallet
Expand All @@ -829,7 +792,11 @@ impl BenchShieldedCtx {
let shielded = async_runtime
.block_on(
ShieldedContext::<BenchShieldedUtils>::gen_shielded_transfer(
&namada, &args,
&namada,
&source,
&target,
&address::nam(),
denominated_amount,
),
)
.unwrap()
Expand Down
14 changes: 10 additions & 4 deletions core/src/ledger/ibc/context/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub use ics23::ProofSpec;
use super::super::Error;
use crate::ledger::storage_api;
use crate::types::address::Address;
use crate::types::ibc::IbcEvent;
use crate::types::ibc::{IbcEvent, IbcShieldedTransfer};
use crate::types::storage::{BlockHeight, Header, Key};
use crate::types::token::DenominatedAmount;

Expand Down Expand Up @@ -55,11 +55,11 @@ pub trait IbcStorageContext {
/// Emit an IBC event
fn emit_ibc_event(&mut self, event: IbcEvent) -> Result<(), Self::Error>;

/// Get an IBC event
fn get_ibc_event(
/// Get IBC events
fn get_ibc_events(
&self,
event_type: impl AsRef<str>,
) -> Result<Option<IbcEvent>, Self::Error>;
) -> Result<Vec<IbcEvent>, Self::Error>;

/// Transfer token
fn transfer_token(
Expand All @@ -70,6 +70,12 @@ pub trait IbcStorageContext {
amount: DenominatedAmount,
) -> Result<(), Self::Error>;

/// Handle masp tx
fn handle_masp_tx(
&mut self,
shielded: &IbcShieldedTransfer,
) -> Result<(), Self::Error>;

/// Mint token
fn mint_token(
&mut self,
Expand Down
Loading

0 comments on commit 97c31d3

Please sign in to comment.