diff --git a/integration_tests/src/lib.rs b/integration_tests/src/lib.rs index bf395101..fe07aee7 100644 --- a/integration_tests/src/lib.rs +++ b/integration_tests/src/lib.rs @@ -12,6 +12,7 @@ use log::info; use sequencer_service_rpc::RpcClient as _; pub use test_fixtures::*; use wallet::{ + AccountIdentity, cli::{ CliAccountMention, Command, SubcommandReturnValue, account::{AccountSubcommand, NewSubcommand}, @@ -19,6 +20,7 @@ use wallet::{ native_token_transfer::AuthTransferSubcommand, token::TokenProgramAgnosticSubcommand, }, }, + program_facades::{native_token_transfer::NativeTokenTransfer, token::Token}, storage::key_chain::FoundPrivateAccount, }; @@ -68,6 +70,34 @@ pub async fn send( Ok(()) } +/// Like [`send`], but for a `to` that is still a fresh, unclaimed account. +/// +/// The wallet CLI's `AuthTransfer::Send` never signs with the recipient's key (by design: the +/// sender's wallet must not sign on behalf of an account it doesn't own). But claiming a fresh +/// account is only possible if that account's own key signs the transaction, so this bypasses +/// the CLI and calls the program facade directly with an explicit `AccountIdentity::Public` for +/// the recipient, using the key the test wallet holds for the account it just created. +/// +/// Unlike `send`, this doesn't go through the CLI's own poll-until-included step, so it waits +/// for block creation itself before returning. +pub async fn send_claiming_new_account( + ctx: &mut TestContext, + from: AccountId, + to: AccountId, + amount: u128, +) -> Result<()> { + NativeTokenTransfer(ctx.wallet()) + .send_public_transfer( + AccountIdentity::Public(from), + AccountIdentity::Public(to), + amount, + ) + .await?; + info!("Waiting for next block creation"); + tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; + Ok(()) +} + /// Create a token (New) and wait for the block to be included. pub async fn create_token( ctx: &mut TestContext, @@ -110,6 +140,26 @@ pub async fn token_send( Ok(()) } +/// Like [`token_send`], but for a `to` that is still a fresh, unclaimed holding account. See +/// [`send_claiming_new_account`] for why the CLI can't be used here. +pub async fn token_send_claiming_new_account( + ctx: &mut TestContext, + from: AccountId, + to: AccountId, + amount: u128, +) -> Result<()> { + Token(ctx.wallet()) + .send_transfer_transaction( + AccountIdentity::Public(from), + AccountIdentity::Public(to), + amount, + ) + .await?; + info!("Waiting for next block creation"); + tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; + Ok(()) +} + /// Retrieve the native token balance for `account_id`. pub async fn account_balance(ctx: &TestContext, account_id: AccountId) -> Result { Ok(ctx diff --git a/integration_tests/tests/amm.rs b/integration_tests/tests/amm.rs index 6e270413..894d787c 100644 --- a/integration_tests/tests/amm.rs +++ b/integration_tests/tests/amm.rs @@ -9,7 +9,7 @@ use std::time::Duration; use anyhow::Result; use integration_tests::{ TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, create_token, get_account, new_account, - public_mention, token_send, + public_mention, token_send_claiming_new_account, }; use log::info; use tokio::test; @@ -54,14 +54,11 @@ async fn amm_public() -> Result<()> { ) .await?; - // Transfer 7 tokens from `supply_acc` to the account at account_id `recipient_account_id_1` - token_send( - &mut ctx, - public_mention(supply_account_id_1), - public_mention(recipient_account_id_1), - 7, - ) - .await?; + // Transfer 7 tokens from `supply_acc` to the account at account_id `recipient_account_id_1`. + // `recipient_account_id_1` is still unclaimed, so this bypasses the wallet CLI (which never + // signs with the recipient's key) and signs with the recipient's own key directly. + token_send_claiming_new_account(&mut ctx, supply_account_id_1, recipient_account_id_1, 7) + .await?; // Create new token create_token( @@ -73,14 +70,10 @@ async fn amm_public() -> Result<()> { ) .await?; - // Transfer 7 tokens from `supply_acc` to the account at account_id `recipient_account_id_2` - token_send( - &mut ctx, - public_mention(supply_account_id_2), - public_mention(recipient_account_id_2), - 7, - ) - .await?; + // Transfer 7 tokens from `supply_acc` to the account at account_id `recipient_account_id_2`. + // `recipient_account_id_2` is still unclaimed, so this bypasses the wallet CLI the same way. + token_send_claiming_new_account(&mut ctx, supply_account_id_2, recipient_account_id_2, 7) + .await?; info!("=================== SETUP FINISHED ==============="); @@ -351,13 +344,9 @@ async fn amm_new_pool_using_labels() -> Result<()> { ) .await?; - token_send( - &mut ctx, - public_mention(supply_account_id_1), - public_mention(holding_a_id), - 5, - ) - .await?; + // `holding_a_id` is still unclaimed, so bypass the wallet CLI (see + // `token_send_claiming_new_account`'s docs for why). + token_send_claiming_new_account(&mut ctx, supply_account_id_1, holding_a_id, 5).await?; // Create token 2 and distribute to holding_b create_token( @@ -369,13 +358,8 @@ async fn amm_new_pool_using_labels() -> Result<()> { ) .await?; - token_send( - &mut ctx, - public_mention(supply_account_id_2), - public_mention(holding_b_id), - 5, - ) - .await?; + // `holding_b_id` is still unclaimed, so bypass the wallet CLI the same way. + token_send_claiming_new_account(&mut ctx, supply_account_id_2, holding_b_id, 5).await?; // Create AMM pool using account labels instead of IDs let subcommand = AmmProgramAgnosticSubcommand::New { diff --git a/integration_tests/tests/auth_transfer/private.rs b/integration_tests/tests/auth_transfer/private.rs index bc5c650b..83a77c4c 100644 --- a/integration_tests/tests/auth_transfer/private.rs +++ b/integration_tests/tests/auth_transfer/private.rs @@ -128,6 +128,47 @@ async fn deshielded_transfer_to_public_account() -> Result<()> { Ok(()) } +/// A deshielded transfer's public recipient must not be asked to sign the transaction: the +/// sender's private-side proof is the only authorization the protocol requires, and signing +/// with the recipient's key (when the wallet happens to hold it) would leak a link between +/// the two accounts. +#[test] +async fn deshielded_transfer_does_not_sign_with_recipient_key() -> Result<()> { + let mut ctx = TestContext::new().await?; + + let from: AccountId = ctx.existing_private_accounts()[0]; + let to: AccountId = ctx.existing_public_accounts()[1]; + + let command = Command::AuthTransfer(AuthTransferSubcommand::Send { + from: private_mention(from), + to: Some(public_mention(to)), + to_npk: None, + to_vpk: None, + to_keys: None, + to_identifier: Some(0), + amount: 100, + }); + + let result = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; + let SubcommandReturnValue::TransactionExecuted { tx_hash } = result else { + anyhow::bail!("Expected TransactionExecuted return value"); + }; + + info!("Waiting for next block creation"); + tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; + + let tx = fetch_privacy_preserving_tx(ctx.sequencer_client(), tx_hash).await; + + assert!( + tx.witness_set().signatures_and_public_keys().is_empty(), + "deshielded transfer must not carry any signature, in particular not the recipient's" + ); + + info!("Deshielded transfer correctly did not sign with the recipient's key"); + + Ok(()) +} + #[test] async fn private_transfer_to_owned_account_using_claiming_path() -> Result<()> { let mut ctx = TestContext::new().await?; diff --git a/integration_tests/tests/auth_transfer/public.rs b/integration_tests/tests/auth_transfer/public.rs index c42bc20c..ea0838ef 100644 --- a/integration_tests/tests/auth_transfer/public.rs +++ b/integration_tests/tests/auth_transfer/public.rs @@ -1,19 +1,19 @@ use std::time::Duration; -use anyhow::Result; +use anyhow::{Context as _, Result}; use common::transaction::LeeTransaction; use integration_tests::{ TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, account_balance, get_account, new_account, - public_mention, send, + public_mention, send, send_claiming_new_account, }; -use lee::public_transaction; +use lee::{PublicKey, public_transaction}; use log::info; use sequencer_service_rpc::RpcClient as _; use tokio::test; use wallet::{ account::Label, cli::{ - CliAccountMention, Command, account::AccountSubcommand, + CliAccountMention, Command, SubcommandReturnValue, account::AccountSubcommand, programs::native_token_transfer::AuthTransferSubcommand, }, }; @@ -24,13 +24,20 @@ async fn successful_transfer_to_existing_account() -> Result<()> { let sender = ctx.existing_public_accounts()[0]; let receiver = ctx.existing_public_accounts()[1]; - send( - &mut ctx, - public_mention(sender), - public_mention(receiver), - 100, - ) - .await?; + + let command = Command::AuthTransfer(AuthTransferSubcommand::Send { + from: public_mention(sender), + to: Some(public_mention(receiver)), + to_npk: None, + to_vpk: None, + to_keys: None, + to_identifier: Some(0), + amount: 100, + }); + let result = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; + let SubcommandReturnValue::TransactionExecuted { tx_hash } = result else { + anyhow::bail!("Expected TransactionExecuted return value"); + }; info!("Waiting for next block creation"); tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; @@ -45,6 +52,34 @@ async fn successful_transfer_to_existing_account() -> Result<()> { assert_eq!(acc_1_balance, 9900); assert_eq!(acc_2_balance, 20100); + // The recipient already exists, so the protocol doesn't require its signature, and the + // wallet must never sign with a key it doesn't need to use. Assert the transfer's witness + // set contains exactly the sender's signature, not the recipient's. + let (tx, _block_id) = ctx + .sequencer_client() + .get_transaction(tx_hash) + .await? + .context("transfer transaction should be included in a block")?; + let LeeTransaction::Public(tx) = tx else { + anyhow::bail!("Expected a public transaction"); + }; + let sender_public_key = PublicKey::new_from_private_key( + ctx.wallet() + .get_account_public_signing_key(sender) + .context("sender should have a signing key")?, + ); + let signers: Vec<_> = tx + .witness_set() + .signatures_and_public_keys() + .iter() + .map(|(_, public_key)| public_key) + .collect(); + assert_eq!( + signers, + vec![&sender_public_key], + "only the sender should sign a transfer to an existing account" + ); + Ok(()) } @@ -55,16 +90,9 @@ pub async fn successful_transfer_to_new_account() -> Result<()> { let new_persistent_account_id = new_account(&mut ctx, false, None).await?; let sender = ctx.existing_public_accounts()[0]; - send( - &mut ctx, - public_mention(sender), - public_mention(new_persistent_account_id), - 100, - ) - .await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; + // The wallet CLI never signs with the recipient's key, but claiming this fresh account + // requires it, so bypass the CLI for this one send. + send_claiming_new_account(&mut ctx, sender, new_persistent_account_id, 100).await?; info!("Checking correct balance move"); let acc_1_balance = account_balance(&ctx, sender).await?; diff --git a/integration_tests/tests/keys.rs b/integration_tests/tests/keys.rs index 10b5710e..4dade59a 100644 --- a/integration_tests/tests/keys.rs +++ b/integration_tests/tests/keys.rs @@ -10,7 +10,7 @@ use anyhow::{Context as _, Result}; use integration_tests::{ TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, assert_public_account_restored, fetch_privacy_preserving_tx, new_account, private_mention, public_mention, - restored_private_account, send, verify_commitment_is_in_state, + restored_private_account, send, send_claiming_new_account, verify_commitment_is_in_state, }; use key_protocol::key_management::key_tree::chain_index::ChainIndex; use lee::AccountId; @@ -121,21 +121,10 @@ async fn restore_keys_from_seed() -> Result<()> { let to_account_id3 = new_account(&mut ctx, false, Some(ChainIndex::root())).await?; let to_account_id4 = new_account(&mut ctx, false, Some(ChainIndex::from_str("/0")?)).await?; - // Send to both public accounts - send( - &mut ctx, - public_mention(from), - public_mention(to_account_id3), - 102, - ) - .await?; - send( - &mut ctx, - public_mention(from), - public_mention(to_account_id4), - 103, - ) - .await?; + // Send to both public accounts. Both are still unclaimed, so bypass the wallet CLI (which + // never signs with the recipient's key) and sign with the recipient's own key directly. + send_claiming_new_account(&mut ctx, from, to_account_id3, 102).await?; + send_claiming_new_account(&mut ctx, from, to_account_id4, 103).await?; info!("Preparation complete, performing keys restoration"); diff --git a/integration_tests/tests/token.rs b/integration_tests/tests/token.rs index d7578a22..215a1065 100644 --- a/integration_tests/tests/token.rs +++ b/integration_tests/tests/token.rs @@ -9,7 +9,7 @@ use std::time::Duration; use anyhow::{Context as _, Result}; use integration_tests::{ TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, get_account, new_account, private_mention, - public_mention, sync_private, verify_commitment_is_in_state, + public_mention, sync_private, token_send_claiming_new_account, verify_commitment_is_in_state, }; use key_protocol::key_management::key_tree::chain_index::ChainIndex; use log::info; @@ -79,22 +79,17 @@ async fn create_and_transfer_public_token() -> Result<()> { } ); - // Transfer 7 tokens from supply_acc to recipient_account_id + // Transfer 7 tokens from supply_acc to recipient_account_id. `recipient_account_id` is + // still unclaimed, so this bypasses the wallet CLI (which never signs with the recipient's + // key) and signs with the recipient's own key directly. let transfer_amount = 7; - let subcommand = TokenProgramAgnosticSubcommand::Send { - from: public_mention(supply_account_id), - to: Some(public_mention(recipient_account_id)), - to_npk: None, - to_vpk: None, - to_keys: None, - to_identifier: Some(0), - amount: transfer_amount, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; + token_send_claiming_new_account( + &mut ctx, + supply_account_id, + recipient_account_id, + transfer_amount, + ) + .await?; // Check the status of the supply account after transfer let supply_acc = get_account(&ctx, supply_account_id).await?; @@ -962,21 +957,28 @@ async fn transfer_token_using_from_label() -> Result<()> { info!("Waiting for next block creation"); tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - // Transfer token using from_label instead of from - let transfer_amount = 20; - let subcommand = TokenProgramAgnosticSubcommand::Send { - from: supply_label.into(), - to: Some(public_mention(recipient_account_id)), - to_npk: None, - to_vpk: None, - to_keys: None, - to_identifier: Some(0), - amount: transfer_amount, - }; - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; + // Confirm the label resolves to the account created for it. + let resolved_sender = ctx + .wallet() + .storage() + .resolve_label(&supply_label) + .context("supply_label should resolve to an account")?; + assert_eq!( + resolved_sender, + wallet::account::AccountIdWithPrivacy::Public(supply_account_id) + ); - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; + // Transfer token from the label-resolved account. `recipient_account_id` is still + // unclaimed, so this bypasses the wallet CLI (which never signs with the recipient's key) + // and signs with the recipient's own key directly. + let transfer_amount = 20; + token_send_claiming_new_account( + &mut ctx, + supply_account_id, + recipient_account_id, + transfer_amount, + ) + .await?; let recipient_acc = get_account(&ctx, recipient_account_id).await?; let token_holding = TokenHolding::try_from(&recipient_acc.data)?; diff --git a/lez/wallet-ffi/src/transfer.rs b/lez/wallet-ffi/src/transfer.rs index 1fcd3133..6f174f98 100644 --- a/lez/wallet-ffi/src/transfer.rs +++ b/lez/wallet-ffi/src/transfer.rs @@ -191,7 +191,7 @@ pub unsafe extern "C" fn wallet_ffi_transfer_shielded( let transfer = NativeTokenTransfer(&wallet); match block_on(transfer.send_shielded_transfer_to_outer_account( - from_mention.into_public_identity(from_id), + from_mention.into_public_identity(from_id, true), to_npk, to_vpk, to_identifier, @@ -464,7 +464,7 @@ pub unsafe extern "C" fn wallet_ffi_transfer_shielded_owned( let transfer = NativeTokenTransfer(&wallet); match block_on(transfer.send_shielded_transfer( - from_mention.into_public_identity(from_id), + from_mention.into_public_identity(from_id, true), to_id, amount, )) { diff --git a/lez/wallet/src/cli/mod.rs b/lez/wallet/src/cli/mod.rs index 16b6073a..03de6e5e 100644 --- a/lez/wallet/src/cli/mod.rs +++ b/lez/wallet/src/cli/mod.rs @@ -159,14 +159,22 @@ impl CliAccountMention { } } + /// Convert to an [`crate::AccountIdentity`] for use in a public transaction. + /// + /// The `sign` flag indicates whether to sign or not with the account keys. #[must_use] - pub fn into_public_identity(self, account_id: lee::AccountId) -> crate::AccountIdentity { + pub fn into_public_identity( + self, + account_id: lee::AccountId, + sign: bool, + ) -> crate::AccountIdentity { match self { Self::KeyPath(key_path) => crate::AccountIdentity::PublicKeycard { account_id, key_path, }, - Self::Id(_) | Self::Label(_) => crate::AccountIdentity::Public(account_id), + Self::Id(_) | Self::Label(_) if sign => crate::AccountIdentity::Public(account_id), + Self::Id(_) | Self::Label(_) => crate::AccountIdentity::PublicNoSign(account_id), } } } diff --git a/lez/wallet/src/cli/programs/amm.rs b/lez/wallet/src/cli/programs/amm.rs index 0f544c42..61f6dfe1 100644 --- a/lez/wallet/src/cli/programs/amm.rs +++ b/lez/wallet/src/cli/programs/amm.rs @@ -138,9 +138,9 @@ impl AmmProgramAgnosticSubcommand { ) => { let tx_hash = Amm(wallet_core) .send_new_definition( - user_holding_a.into_public_identity(a), - user_holding_b.into_public_identity(b), - user_holding_lp.into_public_identity(lp), + user_holding_a.into_public_identity(a, true), + user_holding_b.into_public_identity(b, true), + user_holding_lp.into_public_identity(lp, true), balance_a, balance_b, ) @@ -170,8 +170,8 @@ impl AmmProgramAgnosticSubcommand { (AccountIdWithPrivacy::Public(a), AccountIdWithPrivacy::Public(b)) => { let tx_hash = Amm(wallet_core) .send_swap_exact_input( - user_holding_a.into_public_identity(a), - user_holding_b.into_public_identity(b), + user_holding_a.into_public_identity(a, true), + user_holding_b.into_public_identity(b, true), amount_in, min_amount_out, token_definition, @@ -202,8 +202,8 @@ impl AmmProgramAgnosticSubcommand { (AccountIdWithPrivacy::Public(a), AccountIdWithPrivacy::Public(b)) => { let tx_hash = Amm(wallet_core) .send_swap_exact_output( - user_holding_a.into_public_identity(a), - user_holding_b.into_public_identity(b), + user_holding_a.into_public_identity(a, true), + user_holding_b.into_public_identity(b, true), exact_amount_out, max_amount_in, token_definition, @@ -240,9 +240,9 @@ impl AmmProgramAgnosticSubcommand { ) => { let tx_hash = Amm(wallet_core) .send_add_liquidity( - user_holding_a.into_public_identity(a), - user_holding_b.into_public_identity(b), - user_holding_lp.into_public_identity(lp), + user_holding_a.into_public_identity(a, true), + user_holding_b.into_public_identity(b, true), + user_holding_lp.into_public_identity(lp, true), min_amount_lp, max_amount_a, max_amount_b, @@ -281,7 +281,7 @@ impl AmmProgramAgnosticSubcommand { .send_remove_liquidity( a, b, - user_holding_lp.into_public_identity(lp), + user_holding_lp.into_public_identity(lp, true), balance_lp, min_amount_a, min_amount_b, diff --git a/lez/wallet/src/cli/programs/ata.rs b/lez/wallet/src/cli/programs/ata.rs index 1d207b35..0a9f3221 100644 --- a/lez/wallet/src/cli/programs/ata.rs +++ b/lez/wallet/src/cli/programs/ata.rs @@ -94,7 +94,7 @@ impl AtaSubcommand { match owner_resolved { AccountIdWithPrivacy::Public(owner_id) => { let tx_hash = Ata(wallet_core) - .send_create(owner.into_public_identity(owner_id), definition_id) + .send_create(owner.into_public_identity(owner_id, true), definition_id) .await?; wallet_core .poll_and_finalize_public_transaction(tx_hash) @@ -127,7 +127,7 @@ impl AtaSubcommand { AccountIdWithPrivacy::Public(from_id) => { let tx_hash = Ata(wallet_core) .send_transfer( - from.into_public_identity(from_id), + from.into_public_identity(from_id, true), definition_id, to_id, amount, @@ -162,7 +162,7 @@ impl AtaSubcommand { AccountIdWithPrivacy::Public(holder_id) => { let tx_hash = Ata(wallet_core) .send_burn( - holder.into_public_identity(holder_id), + holder.into_public_identity(holder_id, true), definition_id, amount, ) diff --git a/lez/wallet/src/cli/programs/native_token_transfer.rs b/lez/wallet/src/cli/programs/native_token_transfer.rs index aaa3efe1..8bf3ffe5 100644 --- a/lez/wallet/src/cli/programs/native_token_transfer.rs +++ b/lez/wallet/src/cli/programs/native_token_transfer.rs @@ -61,7 +61,7 @@ impl AuthTransferSubcommand { match resolved { AccountIdWithPrivacy::Public(pub_account_id) => { let tx_hash = NativeTokenTransfer(wallet_core) - .register_account(account_id.into_public_identity(pub_account_id)) + .register_account(account_id.into_public_identity(pub_account_id, true)) .await?; wallet_core @@ -123,8 +123,8 @@ impl AuthTransferSubcommand { (AccountIdWithPrivacy::Public(from), AccountIdWithPrivacy::Public(to)) => { let to_mention = to_account.expect("matched Some branch"); NativeTokenTransferProgramSubcommand::Public { - from: Some(from_account.into_public_identity(from)), - to: Some(to_mention.into_public_identity(to)), + from: Some(from_account.into_public_identity(from, true)), + to: Some(to_mention.into_public_identity(to, false)), amount, } } @@ -143,7 +143,7 @@ impl AuthTransferSubcommand { (AccountIdWithPrivacy::Public(from), AccountIdWithPrivacy::Private(to)) => { NativeTokenTransferProgramSubcommand::Shielded( NativeTokenTransferProgramSubcommandShielded::ShieldedOwned { - from: Some(from_account.into_public_identity(from)), + from: Some(from_account.into_public_identity(from, true)), to, amount, }, @@ -165,7 +165,7 @@ impl AuthTransferSubcommand { AccountIdWithPrivacy::Public(from) => { NativeTokenTransferProgramSubcommand::Shielded( NativeTokenTransferProgramSubcommandShielded::ShieldedForeign { - from: Some(from_account.into_public_identity(from)), + from: Some(from_account.into_public_identity(from, true)), to_npk, to_vpk, to_identifier, diff --git a/lez/wallet/src/cli/programs/token.rs b/lez/wallet/src/cli/programs/token.rs index 6486f58c..bd00edba 100644 --- a/lez/wallet/src/cli/programs/token.rs +++ b/lez/wallet/src/cli/programs/token.rs @@ -208,7 +208,7 @@ impl TokenProgramAgnosticSubcommand { (AccountIdWithPrivacy::Public(from), AccountIdWithPrivacy::Private(to)) => { TokenProgramSubcommand::Shielded( TokenProgramSubcommandShielded::TransferTokenShieldedOwned { - sender: Some(from_mention.into_public_identity(from)), + sender: Some(from_mention.into_public_identity(from, true)), recipient_account_id: to, balance_to_move: amount, }, @@ -237,7 +237,7 @@ impl TokenProgramAgnosticSubcommand { ), AccountIdWithPrivacy::Public(from) => TokenProgramSubcommand::Shielded( TokenProgramSubcommandShielded::TransferTokenShieldedForeign { - sender: Some(from_mention.into_public_identity(from)), + sender: Some(from_mention.into_public_identity(from, true)), recipient_npk: to_npk, recipient_vpk: to_vpk, recipient_identifier: to_identifier, @@ -830,8 +830,8 @@ impl TokenProgramSubcommandPublic { }; let tx_hash = Token(wallet_core) .send_transfer_transaction( - sender_account_id.into_public_identity(sender_id), - recipient_account_id.into_public_identity(recipient_id), + sender_account_id.into_public_identity(sender_id, true), + recipient_account_id.into_public_identity(recipient_id, false), balance_to_move, ) .await?; @@ -855,7 +855,7 @@ impl TokenProgramSubcommandPublic { let tx_hash = Token(wallet_core) .send_burn_transaction( definition_account_id, - holder_account_id.into_public_identity(holder_id), + holder_account_id.into_public_identity(holder_id, true), amount, ) .await?; @@ -881,8 +881,8 @@ impl TokenProgramSubcommandPublic { }; let tx_hash = Token(wallet_core) .send_mint_transaction( - definition_account_id.into_public_identity(def_id), - holder_account_id.into_public_identity(holder_id), + definition_account_id.into_public_identity(def_id, true), + holder_account_id.into_public_identity(holder_id, false), amount, ) .await?; @@ -1546,8 +1546,8 @@ impl CreateNewTokenProgramSubcommand { }; let tx_hash = Token(wallet_core) .send_new_definition( - definition_account_id.into_public_identity(def_id), - supply_account_id.into_public_identity(sup_id), + definition_account_id.into_public_identity(def_id, true), + supply_account_id.into_public_identity(sup_id, true), name, total_supply, ) diff --git a/lez/wallet/src/program_facades/native_token_transfer/deshielded.rs b/lez/wallet/src/program_facades/native_token_transfer/deshielded.rs index f060e0fa..04ca723a 100644 --- a/lez/wallet/src/program_facades/native_token_transfer/deshielded.rs +++ b/lez/wallet/src/program_facades/native_token_transfer/deshielded.rs @@ -19,7 +19,7 @@ impl NativeTokenTransfer<'_> { self.0 .resolve_private_account(from) .ok_or(ExecutionFailureKind::KeyNotFoundError)?, - AccountIdentity::Public(to), + AccountIdentity::PublicNoSign(to), ], instruction_data, &program.into(),