diff --git a/.changelog/unreleased/improvements/3699-disposable-signer-update.md b/.changelog/unreleased/improvements/3699-disposable-signer-update.md new file mode 100644 index 0000000000..d397420470 --- /dev/null +++ b/.changelog/unreleased/improvements/3699-disposable-signer-update.md @@ -0,0 +1,2 @@ +- Made the `disposable-gas-payer` cli arg specific to some transactions. + ([\#3699](https://github.com/anoma/namada/pull/3699)) \ No newline at end of file diff --git a/crates/apps_lib/src/cli.rs b/crates/apps_lib/src/cli.rs index 1859250770..51eacc4cc3 100644 --- a/crates/apps_lib/src/cli.rs +++ b/crates/apps_lib/src/cli.rs @@ -4373,6 +4373,7 @@ pub mod args { std::fs::read(path).expect("Expected a file at given path") }), owner: ctx.borrow_chain_or_exit().get(&self.owner), + disposable_signing_key: self.disposable_signing_key, }) } } @@ -4384,12 +4385,14 @@ pub mod args { let data_path = DATA_PATH_OPT.parse(matches); let serialized_tx = TX_PATH_OPT.parse(matches); let owner = OWNER.parse(matches); + let disposable_signing_key = DISPOSABLE_SIGNING_KEY.parse(matches); Self { tx, code_path, data_path, serialized_tx, owner, + disposable_signing_key, } } @@ -4425,6 +4428,15 @@ pub mod args { "The address corresponding to the signatures or signing \ keys." ))) + .arg( + DISPOSABLE_SIGNING_KEY + .def() + .help(wrap!( + "Generates an ephemeral, disposable keypair to \ + sign the wrapper transaction." + )) + .conflicts_with(FEE_PAYER_OPT.name), + ) } } @@ -4526,6 +4538,7 @@ pub mod args { tx, data, gas_spending_keys, + disposable_signing_key: self.disposable_signing_key, tx_code_path: self.tx_code_path.to_path_buf(), }) } @@ -4549,11 +4562,13 @@ pub mod args { if let Some(key) = GAS_SPENDING_KEY.parse(matches) { gas_spending_keys.push(key); } + let disposable_gas_payer = DISPOSABLE_SIGNING_KEY.parse(matches); Self { tx, data, gas_spending_keys, + disposable_signing_key: disposable_gas_payer, tx_code_path, } } @@ -4580,6 +4595,15 @@ pub mod args { "The optional spending key that will be used in addition \ to the source for gas payment." ))) + .arg( + DISPOSABLE_SIGNING_KEY + .def() + .help(wrap!( + "Generates an ephemeral, disposable keypair to \ + sign the wrapper transaction." + )) + .conflicts_with(FEE_PAYER_OPT.name), + ) } } @@ -4683,6 +4707,7 @@ pub mod args { tx, data, gas_spending_keys, + disposable_signing_key: self.disposable_signing_key, source: chain_ctx.get_cached(&self.source), tx_code_path: self.tx_code_path.to_path_buf(), }) @@ -4706,12 +4731,14 @@ pub mod args { if let Some(key) = GAS_SPENDING_KEY.parse(matches) { gas_spending_keys.push(key); } + let disposable_signing_key = DISPOSABLE_SIGNING_KEY.parse(matches); Self { tx, source, data, gas_spending_keys, + disposable_signing_key, tx_code_path, } } @@ -4738,6 +4765,15 @@ pub mod args { "The optional spending key that will be used in addition \ to the source for gas payment." ))) + .arg( + DISPOSABLE_SIGNING_KEY + .def() + .help(wrap!( + "Generates an ephemeral, disposable keypair to \ + sign the wrapper transaction." + )) + .conflicts_with(FEE_PAYER_OPT.name), + ) } } @@ -4770,6 +4806,7 @@ pub mod args { ibc_shielding_data: self.ibc_shielding_data, ibc_memo: self.ibc_memo, gas_spending_keys, + disposable_signing_key: self.disposable_signing_key, tx_code_path: self.tx_code_path.to_path_buf(), }) } @@ -4799,6 +4836,7 @@ pub mod args { if let Some(key) = GAS_SPENDING_KEY.parse(matches) { gas_spending_keys.push(key); } + let disposable_signing_key = DISPOSABLE_SIGNING_KEY.parse(matches); let tx_code_path = PathBuf::from(TX_IBC_WASM); Self { tx, @@ -4814,6 +4852,7 @@ pub mod args { ibc_shielding_data, ibc_memo, gas_spending_keys, + disposable_signing_key, tx_code_path, } } @@ -4862,6 +4901,15 @@ pub mod args { to the source for gas payment (if this is a shielded \ action)." ))) + .arg( + DISPOSABLE_SIGNING_KEY + .def() + .help(wrap!( + "Generates an ephemeral, disposable keypair to \ + sign the wrapper transaction." + )) + .conflicts_with(FEE_PAYER_OPT.name), + ) } } @@ -6542,6 +6590,7 @@ pub mod args { tx, tx_data, owner: ctx.borrow_chain_or_exit().get(&self.owner), + disposable_signing_key: self.disposable_signing_key, }) } } @@ -6551,10 +6600,12 @@ pub mod args { let tx = Tx::parse(matches); let tx_path = TX_PATH.parse(matches); let owner = OWNER.parse(matches); + let disposable_signing_key = DISPOSABLE_SIGNING_KEY.parse(matches); Self { tx, tx_data: tx_path, owner, + disposable_signing_key, } } @@ -6566,6 +6617,15 @@ pub mod args { .arg( OWNER.def().help(wrap!("The address of the account owner")), ) + .arg( + DISPOSABLE_SIGNING_KEY + .def() + .help(wrap!( + "Generates an ephemeral, disposable keypair to \ + sign the wrapper transaction." + )) + .conflicts_with(FEE_PAYER_OPT.name), + ) } } @@ -7032,7 +7092,6 @@ pub mod args { }) }) .collect::, _>>()?, - disposable_signing_key: self.disposable_signing_key, tx_reveal_code_path: self.tx_reveal_code_path, password: self.password, expiration: self.expiration, @@ -7123,11 +7182,6 @@ pub mod args { )) .conflicts_with_all([EXPIRATION_OPT.name]), ) - .arg(DISPOSABLE_SIGNING_KEY.def().help(wrap!( - "Generates an ephemeral, disposable keypair to sign the \ - wrapper transaction. This keypair will be immediately \ - discarded after use." - ))) .arg( SIGNING_KEYS .def() @@ -7153,16 +7207,13 @@ pub mod args { "The output folder path where the artifact will be stored." ))) .arg(CHAIN_ID_OPT.def().help(wrap!("The chain ID."))) - .arg( - FEE_PAYER_OPT - .def() - .help(wrap!( - "The implicit address of the gas payer. It defaults \ - to the address associated to the first key passed to \ - --signing-keys." - )) - .conflicts_with(DISPOSABLE_SIGNING_KEY.name), - ) + .arg(FEE_PAYER_OPT.def().help(wrap!( + "The implicit address of the gas payer. It defaults to the \ + address associated to the first key passed to \ + --signing-keys. If the specific transaction supports \ + --disposable-signing-key, then this one will overwrite this \ + argument." + ))) .arg( USE_DEVICE .def() @@ -7203,7 +7254,6 @@ pub mod args { let gas_limit = GAS_LIMIT.parse(matches); let wallet_alias_force = WALLET_ALIAS_FORCE.parse(matches); let expiration = EXPIRATION_OPT.parse(matches); - let disposable_signing_key = DISPOSABLE_SIGNING_KEY.parse(matches); let signing_keys = SIGNING_KEYS.parse(matches); let signatures = SIGNATURES.parse(matches); let tx_reveal_code_path = PathBuf::from(TX_REVEAL_PK); @@ -7236,7 +7286,6 @@ pub mod args { fee_token, gas_limit, expiration, - disposable_signing_key, signing_keys, signatures, tx_reveal_code_path, diff --git a/crates/apps_lib/src/client/tx.rs b/crates/apps_lib/src/client/tx.rs index 4d2c2897a9..46e13e71f0 100644 --- a/crates/apps_lib/src/client/tx.rs +++ b/crates/apps_lib/src/client/tx.rs @@ -41,12 +41,19 @@ pub async fn aux_signing_data( args: &args::Tx, owner: Option
, default_signer: Option
, + disposable_signing_key: bool, ) -> Result { - let signing_data = - signing::aux_signing_data(context, args, owner, default_signer, vec![]) - .await?; + let signing_data = signing::aux_signing_data( + context, + args, + owner, + default_signer, + vec![], + disposable_signing_key, + ) + .await?; - if args.disposable_signing_key { + if disposable_signing_key { if !(args.dry_run || args.dry_run_wrapper) { // Store the generated signing key to wallet in case of need context.wallet().await.save().map_err(|_| { @@ -1013,6 +1020,7 @@ pub async fn sign_tx( tx: tx_args, tx_data, owner, + disposable_signing_key, }: args::SignTx, ) -> Result<(), error::Error> where @@ -1025,9 +1033,14 @@ where safe_exit(1) }; let default_signer = Some(owner.clone()); - let signing_data = - aux_signing_data(namada, &tx_args, Some(owner.clone()), default_signer) - .await?; + let signing_data = aux_signing_data( + namada, + &tx_args, + Some(owner.clone()), + default_signer, + disposable_signing_key, + ) + .await?; let mut wallet = namada.wallet_mut().await; diff --git a/crates/apps_lib/src/config/genesis/transactions.rs b/crates/apps_lib/src/config/genesis/transactions.rs index b0e4e4b547..94cc9d038c 100644 --- a/crates/apps_lib/src/config/genesis/transactions.rs +++ b/crates/apps_lib/src/config/genesis/transactions.rs @@ -83,7 +83,6 @@ fn get_tx_args(use_device: bool) -> TxArgs { fee_token: genesis_fee_token_address(), gas_limit: 0.into(), expiration: Default::default(), - disposable_signing_key: false, chain_id: None, signing_keys: vec![], signatures: vec![], diff --git a/crates/sdk/src/args.rs b/crates/sdk/src/args.rs index 59845d5c23..8606bdc291 100644 --- a/crates/sdk/src/args.rs +++ b/crates/sdk/src/args.rs @@ -162,6 +162,9 @@ pub struct TxCustom { pub serialized_tx: Option, /// The address that correspond to the signatures/signing-keys pub owner: C::Address, + /// Generate an ephemeral signing key to be used only once to sign the + /// wrapper tx + pub disposable_signing_key: bool, } impl TxBuilder for TxCustom { @@ -205,6 +208,15 @@ impl TxCustom { pub fn owner(self, owner: C::Address) -> Self { Self { owner, ..self } } + + /// The flag to request an ephemeral signing key to be used only once to + /// sign the wrapper tx + pub fn disposable_signing_key(self, disposable_signing_key: bool) -> Self { + Self { + disposable_signing_key, + ..self + } + } } impl TxCustom { @@ -343,6 +355,9 @@ pub struct TxShieldedTransfer { pub data: Vec>, /// Optional additional keys for gas payment pub gas_spending_keys: Vec, + /// Generate an ephemeral signing key to be used only once to sign the + /// wrapper tx + pub disposable_signing_key: bool, /// Path to the TX WASM code file pub tx_code_path: PathBuf, } @@ -437,6 +452,9 @@ pub struct TxUnshieldingTransfer { pub data: Vec>, /// Optional additional keys for gas payment pub gas_spending_keys: Vec, + /// Generate an ephemeral signing key to be used only once to sign the + /// wrapper tx + pub disposable_signing_key: bool, /// Path to the TX WASM code file pub tx_code_path: PathBuf, } @@ -480,6 +498,9 @@ pub struct TxIbcTransfer { pub ibc_memo: Option, /// Optional additional keys for gas payment pub gas_spending_keys: Vec, + /// Generate an ephemeral signing key to be used only once to sign the + /// wrapper tx + pub disposable_signing_key: bool, /// Path to the TX WASM code file pub tx_code_path: PathBuf, } @@ -2119,6 +2140,8 @@ pub struct SignTx { pub tx_data: C::Data, /// The account address pub owner: C::Address, + /// Flag to request a disposable signer of the wrapper transaction + pub disposable_signing_key: bool, } #[derive(Clone, Debug)] @@ -2279,9 +2302,6 @@ pub struct Tx { pub gas_limit: GasLimit, /// The optional expiration of the transaction pub expiration: TxExpiration, - /// Generate an ephimeral signing key to be used only once to sign a - /// wrapper tx - pub disposable_signing_key: bool, /// The chain id for which the transaction is intended pub chain_id: Option, /// Sign the tx with the key for the given alias from your wallet @@ -2419,14 +2439,6 @@ pub trait TxBuilder: Sized { fn expiration(self, expiration: TxExpiration) -> Self { self.tx(|x| Tx { expiration, ..x }) } - /// Generate an ephimeral signing key to be used only once to sign a - /// wrapper tx - fn disposable_signing_key(self, disposable_signing_key: bool) -> Self { - self.tx(|x| Tx { - disposable_signing_key, - ..x - }) - } /// The chain id for which the transaction is intended fn chain_id(self, chain_id: ChainId) -> Self { self.tx(|x| Tx { diff --git a/crates/sdk/src/eth_bridge/bridge_pool.rs b/crates/sdk/src/eth_bridge/bridge_pool.rs index 90c4686e44..8ec8ec8c90 100644 --- a/crates/sdk/src/eth_bridge/bridge_pool.rs +++ b/crates/sdk/src/eth_bridge/bridge_pool.rs @@ -84,7 +84,8 @@ pub async fn build_bridge_pool_tx( Some(sender_.clone()), // tx signer Some(sender_), - vec![] + vec![], + false, ), )?; let (fee_amount, _) = diff --git a/crates/sdk/src/lib.rs b/crates/sdk/src/lib.rs index b89d702a33..1ebec43146 100644 --- a/crates/sdk/src/lib.rs +++ b/crates/sdk/src/lib.rs @@ -160,7 +160,6 @@ pub trait Namada: Sized + MaybeSync + MaybeSend { fee_token: self.native_token(), gas_limit: GasLimit::from(DEFAULT_GAS_LIMIT), expiration: Default::default(), - disposable_signing_key: false, chain_id: None, signing_keys: vec![], signatures: vec![], @@ -191,11 +190,13 @@ pub trait Namada: Sized + MaybeSync + MaybeSend { &self, data: Vec, gas_spending_keys: Vec, + disposable_signing_key: bool, ) -> args::TxShieldedTransfer { args::TxShieldedTransfer { data, gas_spending_keys, tx_code_path: PathBuf::from(TX_TRANSFER_WASM), + disposable_signing_key, tx: self.tx_builder(), } } @@ -222,11 +223,13 @@ pub trait Namada: Sized + MaybeSync + MaybeSend { source: ExtendedSpendingKey, data: Vec, gas_spending_keys: Vec, + disposable_signing_key: bool, ) -> args::TxUnshieldingTransfer { args::TxUnshieldingTransfer { source, data, gas_spending_keys, + disposable_signing_key, tx_code_path: PathBuf::from(TX_TRANSFER_WASM), tx: self.tx_builder(), } @@ -316,6 +319,7 @@ pub trait Namada: Sized + MaybeSync + MaybeSend { token: Address, amount: InputAmount, channel_id: ChannelId, + disposable_signing_key: bool, ) -> args::TxIbcTransfer { args::TxIbcTransfer { source, @@ -323,6 +327,7 @@ pub trait Namada: Sized + MaybeSync + MaybeSend { token, amount, channel_id, + disposable_signing_key, port_id: PortId::from_str("transfer").unwrap(), timeout_height: None, timeout_sec_offset: None, @@ -610,6 +615,7 @@ pub trait Namada: Sized + MaybeSync + MaybeSend { code_path: None, data_path: None, serialized_tx: None, + disposable_signing_key: false, } } @@ -732,7 +738,6 @@ where fee_token: native_token, gas_limit: GasLimit::from(DEFAULT_GAS_LIMIT), expiration: Default::default(), - disposable_signing_key: false, chain_id: None, signing_keys: vec![], signatures: vec![], diff --git a/crates/sdk/src/signing.rs b/crates/sdk/src/signing.rs index 9e487522cc..b8454f68b9 100644 --- a/crates/sdk/src/signing.rs +++ b/crates/sdk/src/signing.rs @@ -295,6 +295,7 @@ pub async fn aux_signing_data( owner: Option
, default_signer: Option
, extra_public_keys: Vec, + disposable_signing_key: bool, ) -> Result { let mut public_keys = tx_signers(context, args, default_signer.clone()).await?; @@ -330,7 +331,7 @@ pub async fn aux_signing_data( ), }; - let fee_payer = if args.disposable_signing_key { + let fee_payer = if disposable_signing_key { context .wallet_mut() .await diff --git a/crates/sdk/src/tx.rs b/crates/sdk/src/tx.rs index 5562748b8f..dab56b7982 100644 --- a/crates/sdk/src/tx.rs +++ b/crates/sdk/src/tx.rs @@ -314,6 +314,7 @@ pub async fn build_reveal_pk( None, Some(public_key.into()), vec![], + false, ) .await?; let (fee_amount, _) = @@ -570,6 +571,7 @@ pub async fn build_change_consensus_key( None, None, vec![consensus_key.clone()], + false, ) .await?; @@ -607,6 +609,7 @@ pub async fn build_validator_commission_change( Some(validator.clone()), default_signer, vec![], + false, ) .await?; let (fee_amount, _) = @@ -749,6 +752,7 @@ pub async fn build_validator_metadata_change( Some(validator.clone()), default_signer, vec![], + false, ) .await?; let (fee_amount, _) = @@ -962,6 +966,7 @@ pub async fn build_update_steward_commission( Some(steward.clone()), default_signer, vec![], + false, ) .await?; let (fee_amount, _) = @@ -1030,6 +1035,7 @@ pub async fn build_resign_steward( Some(steward.clone()), default_signer, vec![], + false, ) .await?; let (fee_amount, _) = @@ -1078,6 +1084,7 @@ pub async fn build_unjail_validator( Some(validator.clone()), default_signer, vec![], + false, ) .await?; let (fee_amount, _) = @@ -1182,6 +1189,7 @@ pub async fn build_deactivate_validator( Some(validator.clone()), default_signer, vec![], + false, ) .await?; let (fee_amount, _) = @@ -1257,6 +1265,7 @@ pub async fn build_reactivate_validator( Some(validator.clone()), default_signer, vec![], + false, ) .await?; let (fee_amount, _) = @@ -1478,6 +1487,7 @@ pub async fn build_redelegation( Some(default_address), default_signer, vec![], + false, ) .await?; let (fee_amount, _) = @@ -1522,6 +1532,7 @@ pub async fn build_withdraw( Some(default_address), default_signer, vec![], + false, ) .await?; let (fee_amount, _) = @@ -1609,6 +1620,7 @@ pub async fn build_claim_rewards( Some(default_address), default_signer, vec![], + false, ) .await?; let (fee_amount, _) = @@ -1713,6 +1725,7 @@ pub async fn build_unbond( Some(default_address), default_signer, vec![], + false, ) .await?; let (fee_amount, _) = @@ -1948,6 +1961,7 @@ pub async fn build_bond( Some(default_address.clone()), default_signer, vec![], + false, ) .await?; let (fee_amount, updated_balance) = @@ -2013,6 +2027,7 @@ pub async fn build_default_proposal( Some(proposal.proposal.author.clone()), default_signer, vec![], + false, ) .await?; let (fee_amount, _updated_balance) = @@ -2067,6 +2082,7 @@ pub async fn build_vote_proposal( default_signer.clone(), default_signer.clone(), vec![], + false, ) .await?; let (fee_amount, _) = @@ -2369,7 +2385,7 @@ pub async fn build_become_validator( all_pks.push(protocol_key.clone().unwrap().clone()); let signing_data = - signing::aux_signing_data(context, tx_args, None, None, all_pks) + signing::aux_signing_data(context, tx_args, None, None, all_pks, false) .await?; let (fee_amount, _updated_balance) = @@ -2408,6 +2424,7 @@ pub async fn build_pgf_funding_proposal( Some(proposal.proposal.author.clone()), default_signer, vec![], + false, ) .await?; let (fee_amount, _updated_balance) = @@ -2454,6 +2471,7 @@ pub async fn build_pgf_stewards_proposal( Some(proposal.proposal.author.clone()), default_signer, vec![], + false, ) .await?; let (fee_amount, _updated_balance) = @@ -2505,6 +2523,7 @@ pub async fn build_ibc_transfer( Some(source.clone()), Some(source.clone()), vec![], + args.disposable_signing_key, ) .await?; let (fee_per_gas_unit, updated_balance) = @@ -2906,6 +2925,7 @@ pub async fn build_transparent_transfer( source.clone(), source, vec![], + false, ) .await?; @@ -2996,6 +3016,7 @@ pub async fn build_shielded_transfer( Some(MASP), Some(MASP), vec![], + args.disposable_signing_key, ) .await?; @@ -3148,6 +3169,7 @@ pub async fn build_shielding_transfer( source.clone(), source, vec![], + false, ) .await?; @@ -3273,6 +3295,7 @@ pub async fn build_unshielding_transfer( Some(MASP), Some(MASP), vec![], + args.disposable_signing_key, ) .await?; @@ -3460,7 +3483,8 @@ pub async fn build_init_account( }: &args::TxInitAccount, ) -> Result<(Tx, SigningTxData)> { let signing_data = - signing::aux_signing_data(context, tx_args, None, None, vec![]).await?; + signing::aux_signing_data(context, tx_args, None, None, vec![], false) + .await?; let (fee_amount, _) = validate_transparent_fee(context, tx_args, &signing_data.fee_payer) .await?; @@ -3547,6 +3571,7 @@ pub async fn build_update_account( Some(addr.clone()), default_signer, vec![], + false, ) .await?; let (fee_amount, _) = @@ -3663,6 +3688,7 @@ pub async fn build_custom( data_path, serialized_tx, owner, + disposable_signing_key, }: &args::TxCustom, ) -> Result<(Tx, SigningTxData)> { let default_signer = Some(owner.clone()); @@ -3672,6 +3698,7 @@ pub async fn build_custom( Some(owner.clone()), default_signer, vec![], + *disposable_signing_key, ) .await?; let fee_amount = validate_fee(context, tx_args).await?;