diff --git a/.changelog/unreleased/bug-fixes/3730-enable-hw-fallback.md b/.changelog/unreleased/bug-fixes/3730-enable-hw-fallback.md new file mode 100644 index 0000000000..f6d75791c5 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/3730-enable-hw-fallback.md @@ -0,0 +1,3 @@ +- Enable the signing logic to fall back to the hardware wallet + if a secret key is not found in software wallet store. + ([\#3730](https://github.com/anoma/namada/pull/3730)) \ No newline at end of file diff --git a/crates/sdk/src/signing.rs b/crates/sdk/src/signing.rs index 8d10bef5f7..4b5bd1f42c 100644 --- a/crates/sdk/src/signing.rs +++ b/crates/sdk/src/signing.rs @@ -232,7 +232,13 @@ where for public_key in &signing_data.public_keys { if !used_pubkeys.contains(public_key) { - let secret_key = find_key_by_pk(&mut wallet, args, public_key)?; + let Ok(secret_key) = + find_key_by_pk(&mut wallet, args, public_key) + else { + // If the secret key is not found, continue because the + // hardware wallet may still be able to sign this + continue; + }; used_pubkeys.insert(public_key.clone()); signing_tx_keypairs.push(secret_key); } @@ -248,8 +254,8 @@ where } // Then try to sign the raw header using the hardware wallet - for pubkey in signing_data.public_keys { - if !used_pubkeys.contains(&pubkey) && pubkey != signing_data.fee_payer { + for pubkey in &signing_data.public_keys { + if !used_pubkeys.contains(pubkey) && *pubkey != signing_data.fee_payer { if let Ok(ntx) = sign( tx.clone(), pubkey.clone(), @@ -276,7 +282,10 @@ where Ok(fee_payer_keypair) => { tx.sign_wrapper(fee_payer_keypair); } - Err(_) => { + // The case where tge fee payer also signs the inner transaction + Err(_) + if signing_data.public_keys.contains(&signing_data.fee_payer) => + { *tx = sign( tx.clone(), signing_data.fee_payer.clone(), @@ -284,9 +293,32 @@ where user_data, ) .await?; + used_pubkeys.insert(signing_data.fee_payer.clone()); + } + // The case where the fee payer does not sign the inner transaction + Err(_) => { + *tx = sign( + tx.clone(), + signing_data.fee_payer.clone(), + HashSet::from([Signable::FeeHeader]), + user_data, + ) + .await?; } } - Ok(()) + // Then make sure that the number of public keys used exceeds the threshold + let used_pubkeys_len = used_pubkeys + .len() + .try_into() + .expect("Public keys associated with account exceed 127"); + if used_pubkeys_len < signing_data.threshold { + Err(Error::from(TxSubmitError::MissingSigningKeys( + signing_data.threshold, + used_pubkeys_len, + ))) + } else { + Ok(()) + } } /// Return the necessary data regarding an account to be able to generate a