Merge #1607: Hint user if the key of signing device is not part of the wallet descriptor
c8e455c8ceb2a7b5408380dbe3cd30ce3959ff57 lianad: add a test for LianaDescriptor::contains_fingerprint() (pythcoiner) aead34cc8eaa3e74d2c76c7e1e8341d756d779a2 installer: hint the user if the plugged signing device is not part of the descriptor (pythcoiner) 5ae13dd025c2e038e17746f5bfc8cf72ec5120c7 liana-ui: make it more clear when a device key is not part of the wallet descriptor (pythcoiner) fa8fd4782f97b8969f6a655e0511bf8f96924232 liana: implement LianaDescriptor::contains_fingerprint() (pythcoiner) Pull request description: This PR: - [x] Add `LianaDescriptor::contains_fingerprint()` method - [x] make more explicit when a signing device is not part of the wallet descriptor before (user had to hover the button to see the tooltip):  after:  - [x] Hint the user in the installer if the plugged device is not part of the created/imported descriptor:  ACKs for top commit: jp1ac4: tACK c8e455c8ceb2a7b5408380dbe3cd30ce3959ff57. Tree-SHA512: 092b8cb6efe6b6a6dc4f8505649783cb7c83c231242ab14f479b573e12cd61bab4e6e27a173bee19097d3ad90a8f1e578ecf4b699a4a481b40588f5f60cb9c71
This commit is contained in:
commit
9fc7c093ff
@ -501,6 +501,7 @@ impl super::DescriptorEditModal for EditXpubModal {
|
||||
hw.fingerprint() == chosen_signer,
|
||||
self.processing,
|
||||
hw.fingerprint() == chosen_signer,
|
||||
None,
|
||||
self.device_must_support_tapminiscript,
|
||||
))
|
||||
}
|
||||
|
||||
@ -306,10 +306,11 @@ impl Step for RegisterDescriptor {
|
||||
email: Option<&'a str>,
|
||||
) -> Element<'a, Message> {
|
||||
let desc = self.descriptor.as_ref().unwrap();
|
||||
|
||||
view::register_descriptor(
|
||||
progress,
|
||||
email,
|
||||
desc.to_string(),
|
||||
desc,
|
||||
&hws.list,
|
||||
&self.registered,
|
||||
self.error.as_ref(),
|
||||
|
||||
@ -589,7 +589,7 @@ pub fn share_xpubs<'a>(
|
||||
pub fn register_descriptor<'a>(
|
||||
progress: (usize, usize),
|
||||
email: Option<&'a str>,
|
||||
descriptor: String,
|
||||
descriptor: &'a LianaDescriptor,
|
||||
hws: &'a [HardwareWallet],
|
||||
registered: &HashSet<bitcoin::bip32::Fingerprint>,
|
||||
error: Option<&Error>,
|
||||
@ -598,8 +598,9 @@ pub fn register_descriptor<'a>(
|
||||
done: bool,
|
||||
created_desc: bool,
|
||||
) -> Element<'a, Message> {
|
||||
let descriptor_str = descriptor.to_string();
|
||||
let displayed_descriptor =
|
||||
if let Ok((template, keys)) = extract_keys_and_template::<String>(&descriptor) {
|
||||
if let Ok((template, keys)) = extract_keys_and_template::<String>(&descriptor_str) {
|
||||
let mut col = Column::new()
|
||||
.push(
|
||||
card::simple(
|
||||
@ -656,7 +657,7 @@ pub fn register_descriptor<'a>(
|
||||
.push(
|
||||
scrollable(
|
||||
Column::new()
|
||||
.push(text(descriptor.to_owned()).small())
|
||||
.push(text(descriptor_str.to_owned()).small())
|
||||
.push(Space::with_height(Length::Fixed(5.0))),
|
||||
)
|
||||
.direction(scrollable::Direction::Horizontal(
|
||||
@ -666,7 +667,7 @@ pub fn register_descriptor<'a>(
|
||||
.push(
|
||||
Row::new().push(Column::new().width(Length::Fill)).push(
|
||||
button::secondary(Some(icon::clipboard_icon()), "Copy")
|
||||
.on_press(Message::Clibpboard(descriptor)),
|
||||
.on_press(Message::Clibpboard(descriptor_str)),
|
||||
),
|
||||
)
|
||||
.spacing(10),
|
||||
@ -710,6 +711,7 @@ pub fn register_descriptor<'a>(
|
||||
hw.fingerprint()
|
||||
.map(|fg| registered.contains(&fg))
|
||||
.unwrap_or(false),
|
||||
Some(descriptor),
|
||||
false,
|
||||
))
|
||||
}),
|
||||
@ -1648,14 +1650,16 @@ pub fn defined_sequence<'a>(
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn hw_list_view(
|
||||
pub fn hw_list_view<'a>(
|
||||
i: usize,
|
||||
hw: &HardwareWallet,
|
||||
hw: &'a HardwareWallet,
|
||||
chosen: bool,
|
||||
processing: bool,
|
||||
selected: bool,
|
||||
descriptor: Option<&'a LianaDescriptor>,
|
||||
device_must_support_taproot: bool,
|
||||
) -> Element<Message> {
|
||||
) -> Element<'a, Message> {
|
||||
let mut unrelated = false;
|
||||
let mut bttn = Button::new(match hw {
|
||||
HardwareWallet::Supported {
|
||||
kind,
|
||||
@ -1664,9 +1668,15 @@ pub fn hw_list_view(
|
||||
alias,
|
||||
..
|
||||
} => {
|
||||
let device_in_descriptor = descriptor
|
||||
.map(|d| d.contains_fingerprint(*fingerprint))
|
||||
.unwrap_or(true);
|
||||
let not_tapminiscript = device_must_support_taproot
|
||||
&& !is_compatible_with_tapminiscript(kind, version.as_ref());
|
||||
if chosen && processing {
|
||||
if !device_in_descriptor {
|
||||
unrelated = true;
|
||||
hw::unrelated_hardware_wallet(kind.to_string(), version.as_ref(), fingerprint)
|
||||
} else if chosen && processing {
|
||||
hw::processing_hardware_wallet(kind, version.as_ref(), fingerprint, alias.as_ref())
|
||||
} else if selected {
|
||||
hw::selected_hardware_wallet(kind, version.as_ref(), fingerprint, alias.as_ref(), {
|
||||
@ -1715,7 +1725,7 @@ pub fn hw_list_view(
|
||||
})
|
||||
.style(theme::button::secondary)
|
||||
.width(Length::Fill);
|
||||
if !processing && hw.is_supported() {
|
||||
if !processing && hw.is_supported() && !unrelated {
|
||||
bttn = bttn.on_press(Message::Select(i));
|
||||
}
|
||||
bttn.into()
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use crate::{color, component::text, icon, image, theme, widget::*};
|
||||
use iced::{
|
||||
widget::{column, container, row, tooltip},
|
||||
alignment::Vertical,
|
||||
widget::{column, container, row, tooltip, Space},
|
||||
Alignment, Length,
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
@ -129,24 +130,28 @@ pub fn unrelated_hardware_wallet<'a, T: 'a, K: Display, V: Display, F: Display>(
|
||||
version: Option<V>,
|
||||
fingerprint: F,
|
||||
) -> Container<'a, T> {
|
||||
container(
|
||||
tooltip::Tooltip::new(
|
||||
container(
|
||||
column(vec![
|
||||
let key = column(vec![
|
||||
text::p1_regular(format!("#{}", fingerprint)).into(),
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.push(text::caption(kind.to_string()))
|
||||
.push_maybe(version.map(|v| text::caption(v.to_string())))
|
||||
.into(),
|
||||
])
|
||||
.width(Length::Fill),
|
||||
]);
|
||||
container(
|
||||
container(
|
||||
Row::new()
|
||||
.push(key)
|
||||
.push(Space::with_width(15))
|
||||
.push(Space::with_width(Length::Fill))
|
||||
.push(text::text(
|
||||
"This signing device is not related to this Liana wallet.",
|
||||
))
|
||||
.push(Space::with_width(Length::Fill))
|
||||
.align_y(Vertical::Center),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
.padding(10),
|
||||
"This signer does not have a key in this wallet.",
|
||||
tooltip::Position::Bottom,
|
||||
)
|
||||
.padding(10)
|
||||
.style(theme::card::simple),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use miniscript::{
|
||||
bitcoin::{
|
||||
self, bip32,
|
||||
self,
|
||||
bip32::{self, Fingerprint},
|
||||
constants::WITNESS_SCALE_FACTOR,
|
||||
psbt::{Input as PsbtIn, Output as PsbtOut, Psbt},
|
||||
secp256k1,
|
||||
@ -210,6 +211,12 @@ impl LianaDescriptor {
|
||||
})
|
||||
}
|
||||
|
||||
/// Whether a key matching this fingerprint is part of this descriptor
|
||||
pub fn contains_fingerprint(&self, fg: Fingerprint) -> bool {
|
||||
self.multi_desc
|
||||
.for_any_key(|k| k.master_fingerprint() == fg)
|
||||
}
|
||||
|
||||
/// Get the descriptor for receiving addresses.
|
||||
pub fn receive_descriptor(&self) -> &SinglePathLianaDesc {
|
||||
&self.receive_desc
|
||||
@ -2202,5 +2209,15 @@ mod tests {
|
||||
LianaDescriptor::from_str("wsh(0)").unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn descriptor_contains_fingerprint() {
|
||||
let descr = LianaDescriptor::from_str("wsh(or_d(multi(3,[aabb0011/48'/0'/0'/2']xpub6Eze7yAT3Y1wGrnzedCNVYDXUqa9NmHVWck5emBaTbXtURbe1NWZbK9bsz1TiVE7Cz341PMTfYgFw1KdLWdzcM1UMFTcdQfCYhhXZ2HJvTW/0/<0;1>/*,[aabb0012/48'/0'/0'/2']xpub6Bw79HbNSeS2xXw1sngPE3ehnk1U3iSPCgLYzC9LpN8m9nDuaKLZvkg8QXxL5pDmEmQtYscmUD8B9MkAAZbh6vxPzNXMaLfGQ9Sb3z85qhR/0/<0;1>/*,[aabb0013/48'/0'/0'/2']xpub67zuTXF9Ln4731avKTBSawoVVNRuMfmRvkL7kLUaLBRqma9ZqdHBJg9qx8cPUm3oNQMiXT4TmGovXNoQPuwg17RFcVJ8YrnbcooN7pxVJqC/0/<0;1>/*),and_v(v:thresh(2,pkh([aabb0011/48'/0'/0'/2']xpub6Eze7yAT3Y1wGrnzedCNVYDXUqa9NmHVWck5emBaTbXtURbe1NWZbK9bsz1TiVE7Cz341PMTfYgFw1KdLWdzcM1UMFTcdQfCYhhXZ2HJvTW/1/<0;1>/*),a:pkh([aabb0012/48'/0'/0'/2']xpub6Bw79HbNSeS2xXw1sngPE3ehnk1U3iSPCgLYzC9LpN8m9nDuaKLZvkg8QXxL5pDmEmQtYscmUD8B9MkAAZbh6vxPzNXMaLfGQ9Sb3z85qhR/1/<0;1>/*),a:pkh([aabb0013/48'/0'/0'/2']xpub67zuTXF9Ln4731avKTBSawoVVNRuMfmRvkL7kLUaLBRqma9ZqdHBJg9qx8cPUm3oNQMiXT4TmGovXNoQPuwg17RFcVJ8YrnbcooN7pxVJqC/1/<0;1>/*)),older(26352))))").unwrap();
|
||||
|
||||
assert!(descr.contains_fingerprint(Fingerprint::from_str("aabb0011").unwrap()));
|
||||
assert!(descr.contains_fingerprint(Fingerprint::from_str("aabb0012").unwrap()));
|
||||
assert!(descr.contains_fingerprint(Fingerprint::from_str("aabb0013").unwrap()));
|
||||
assert!(!descr.contains_fingerprint(Fingerprint::from_str("aabb0014").unwrap()));
|
||||
}
|
||||
|
||||
// TODO: test error conditions of deserialization.
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user