Merge #751: GUI: prune BIP32 derivations for other spending paths when signing with BitBox02

99bbb76228de0762521cf9152fa35e267fca95b2 gui: prune bip32 derivations when signing with BitBox02 (Antoine Poinsot)
b8d6be82a7c9da80333d7470f6079d95e87210b8 gui: update to latest Liana (Antoine Poinsot)

Pull request description:

ACKs for top commit:
  edouardparis:
    ACK 99bbb76228de0762521cf9152fa35e267fca95b2

Tree-SHA512: 31476a0db1af0d3ce114c6709ec8e693bc9209475da532c541530ad6b96837a3eb4faf0e5061255c93c9adaab9b48503878966bf3a2aec4b7be34e729e2e1056
This commit is contained in:
Antoine Poinsot 2023-10-30 15:05:19 +01:00
commit 4de9772a93
No known key found for this signature in database
GPG Key ID: E13FC145CD3F4304
4 changed files with 35 additions and 4 deletions

2
gui/Cargo.lock generated
View File

@ -2415,7 +2415,7 @@ dependencies = [
[[package]]
name = "liana"
version = "2.0.0"
source = "git+https://github.com/wizardsardine/liana?branch=master#42578609e2ed340d277d75c747c74449308acbb7"
source = "git+https://github.com/wizardsardine/liana?branch=master#87555a8da50702ebec04dbe876e7055432ca805a"
dependencies = [
"backtrace",
"bip39",

View File

@ -1,7 +1,7 @@
use std::convert::From;
use std::io::ErrorKind;
use liana::config::ConfigError;
use liana::{config::ConfigError, descriptors::LianaDescError};
use crate::{
app::{settings::SettingsError, wallet::WalletError},
@ -15,6 +15,7 @@ pub enum Error {
Daemon(DaemonError),
Unexpected(String),
HardwareWallet(async_hwi::Error),
Desc(LianaDescError),
}
impl std::fmt::Display for Error {
@ -48,6 +49,7 @@ impl std::fmt::Display for Error {
},
Self::Unexpected(e) => write!(f, "Unexpected error: {}", e),
Self::HardwareWallet(e) => write!(f, "{}", e),
Self::Desc(e) => write!(f, "Liana descriptor error: {}", e),
}
}
}

View File

@ -365,7 +365,7 @@ impl Action for SignAction {
self.processing = true;
let psbt = tx.psbt.clone();
return Command::perform(
sign_psbt(device.clone(), *fingerprint, psbt),
sign_psbt(self.wallet.clone(), device.clone(), *fingerprint, psbt),
Message::Signed,
);
}
@ -449,11 +449,39 @@ async fn sign_psbt_with_hot_signer(
}
async fn sign_psbt(
wallet: Arc<Wallet>,
hw: std::sync::Arc<dyn async_hwi::HWI + Send + Sync>,
fingerprint: Fingerprint,
mut psbt: Psbt,
) -> Result<(Psbt, Fingerprint), Error> {
hw.sign_tx(&mut psbt).await.map_err(Error::from)?;
// The BitBox02 is only going to produce a signature for a single key in the Script. In order
// to make sure it doesn't sign for a public key from another spending path we remove the BIP32
// derivation for the other paths.
if matches!(hw.device_kind(), async_hwi::DeviceKind::BitBox02) {
// We need to make sure we don't prune the BIP32 derivations from the original PSBT (which
// would end up being updated in the daemon's database and erase the previously unpruned
// one). To this end we create a new, pruned, psbt we use for signing and then merge its
// signatures back into the original PSBT.
let mut pruned_psbt = wallet
.main_descriptor
.prune_bip32_derivs_last_avail(psbt.clone())
.map_err(Error::Desc)?;
hw.sign_tx(&mut pruned_psbt).await.map_err(Error::from)?;
for (i, psbt_in) in psbt.inputs.iter_mut().enumerate() {
if let Some(pruned_psbt_in) = pruned_psbt.inputs.get_mut(i) {
psbt_in
.partial_sigs
.append(&mut pruned_psbt_in.partial_sigs);
} else {
log::error!(
"Not all PSBT inputs are present in the pruned psbt. Pruned psbt: '{}'.",
&pruned_psbt
);
}
}
} else {
hw.sign_tx(&mut psbt).await.map_err(Error::from)?;
}
Ok((psbt, fingerprint))
}

View File

@ -37,6 +37,7 @@ impl From<&Error> for WarningMessage {
},
Error::Unexpected(_) => WarningMessage("Unknown error".to_string()),
Error::HardwareWallet(_) => WarningMessage("Hardware wallet error".to_string()),
Error::Desc(e) => WarningMessage(format!("Descriptor analysis error: '{}'.", e)),
}
}
}