installer: use appended path instead of account number for xpubs

This commit is contained in:
edouard 2023-07-20 18:04:18 +02:00
parent 6c969aeacd
commit 30ce2dea08
11 changed files with 460 additions and 453 deletions

10
gui/Cargo.lock generated
View File

@ -133,9 +133,9 @@ dependencies = [
[[package]]
name = "async-hwi"
version = "0.0.9"
version = "0.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85192c0f286ebcf3f154ea7220ac343a097aa327a0e748c001b685a0c7f05e4f"
checksum = "22355924b351ed9bad0e8b400d0b039eb624259e80ad4afb978e04a35e81ea93"
dependencies = [
"async-trait",
"base64 0.13.1",
@ -1907,9 +1907,9 @@ dependencies = [
[[package]]
name = "ledger_bitcoin_client"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd0a13c32d94c0313fa58f77f14f7aa425fddc6cd13aa375bde12f98740f0e6a"
checksum = "53b3850bd03537874d58c09dcdd15cfab272b3e9d3381e57843b4f9e1c9ceae7"
dependencies = [
"async-trait",
"bitcoin",
@ -1919,7 +1919,7 @@ dependencies = [
[[package]]
name = "liana"
version = "1.0.0"
source = "git+https://github.com/wizardsardine/liana?branch=master#ebea147c2fd6768a8fee9aea8255721e305d568d"
source = "git+https://github.com/wizardsardine/liana?branch=master#6c969aeacdde28a84f0a04060b280343a1e22afe"
dependencies = [
"backtrace",
"bip39",

View File

@ -14,7 +14,7 @@ name = "liana-gui"
path = "src/main.rs"
[dependencies]
async-hwi = "0.0.9"
async-hwi = "0.0.10"
liana = { git = "https://github.com/wizardsardine/liana", branch = "master", default-features = false }
liana_ui = { path = "ui" }
backtrace = "0.3"

View File

@ -136,24 +136,28 @@ mod tests {
amount: bitcoin::Amount::from_sat(1),
block_height: Some(3),
spend_info: None,
is_immature: false,
},
Coin {
outpoint: bitcoin::OutPoint { txid, vout: 3 },
amount: bitcoin::Amount::from_sat(1),
block_height: None,
spend_info: None,
is_immature: false,
},
Coin {
outpoint: bitcoin::OutPoint { txid, vout: 0 },
amount: bitcoin::Amount::from_sat(1),
block_height: Some(2),
spend_info: None,
is_immature: false,
},
Coin {
outpoint: bitcoin::OutPoint { txid, vout: 1 },
amount: bitcoin::Amount::from_sat(1),
block_height: Some(3),
spend_info: None,
is_immature: false,
},
]);

View File

@ -1,3 +1,4 @@
use std::collections::HashSet;
use std::str::FromStr;
use std::sync::Arc;
@ -197,7 +198,7 @@ impl From<RecoveryPanel> for Box<dyn State> {
pub struct RecoveryPath {
threshold: usize,
sequence: u16,
origins: Vec<(Fingerprint, DerivationPath)>,
origins: Vec<(Fingerprint, HashSet<DerivationPath>)>,
total_amount: Amount,
number_of_coins: usize,
}

View File

@ -309,19 +309,19 @@ pub fn signatures<'a>(
sigs.signed_pubkeys
.keys()
.fold(Row::new().spacing(5), |row, value| {
row.push(if let Some(alias) = keys_aliases.get(&value.0) {
row.push(if let Some(alias) = keys_aliases.get(value) {
Container::new(
tooltip::Tooltip::new(
Container::new(text(alias))
.padding(10)
.style(theme::Container::Pill(theme::Pill::Simple)),
value.0.to_string(),
value.to_string(),
tooltip::Position::Bottom,
)
.style(theme::Container::Card(theme::Card::Simple)),
)
} else {
Container::new(text(value.0.to_string()))
Container::new(text(value.to_string()))
.padding(10)
.style(theme::Container::Pill(theme::Pill::Simple))
})
@ -401,14 +401,14 @@ pub fn path_view<'a>(
sigs: &'a PathSpendInfo,
key_aliases: &'a HashMap<Fingerprint, String>,
) -> Element<'a, Message> {
let mut keys: Vec<(Fingerprint, DerivationPath)> =
let mut keys: Vec<(Fingerprint, HashSet<DerivationPath>)> =
path.thresh_origins().1.into_iter().collect();
let missing_signatures = if sigs.sigs_count >= sigs.threshold {
0
} else {
sigs.threshold - sigs.sigs_count
};
keys.sort();
keys.sort_by_key(|a| a.0);
scrollable(
Row::new()
.align_items(Alignment::Center)
@ -439,7 +439,7 @@ pub fn path_view<'a>(
None
} else {
Some(keys.iter().fold(Row::new().spacing(5), |row, value| {
row.push_maybe(if !sigs.signed_pubkeys.contains_key(value) {
row.push_maybe(if !sigs.signed_pubkeys.contains_key(&value.0) {
Some(if let Some(alias) = key_aliases.get(&value.0) {
Container::new(
tooltip::Tooltip::new(
@ -470,19 +470,19 @@ pub fn path_view<'a>(
sigs.signed_pubkeys
.keys()
.fold(Row::new().spacing(5), |row, value| {
row.push(if let Some(alias) = key_aliases.get(&value.0) {
row.push(if let Some(alias) = key_aliases.get(value) {
Container::new(
tooltip::Tooltip::new(
Container::new(text(alias))
.padding(10)
.style(theme::Container::Pill(theme::Pill::Simple)),
value.0.to_string(),
value.to_string(),
tooltip::Position::Bottom,
)
.style(theme::Container::Card(theme::Card::Simple)),
)
} else {
Container::new(text(value.0.to_string()))
Container::new(text(value.to_string()))
.padding(10)
.style(theme::Container::Pill(theme::Pill::Simple))
})

View File

@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use iced::{
widget::{checkbox, tooltip, Space},
@ -137,7 +137,7 @@ pub fn recovery<'a>(
pub fn recovery_path_view<'a>(
index: usize,
threshold: usize,
origins: &'a [(Fingerprint, DerivationPath)],
origins: &'a [(Fingerprint, HashSet<DerivationPath>)],
total_amount: Amount,
number_of_coins: usize,
key_aliases: &'a HashMap<Fingerprint, String>,

View File

@ -106,12 +106,12 @@ impl SpendTx {
pub fn signers(&self) -> HashSet<Fingerprint> {
let mut signers = HashSet::new();
for (fg, _) in self.sigs.primary_path().signed_pubkeys.keys() {
for fg in self.sigs.primary_path().signed_pubkeys.keys() {
signers.insert(*fg);
}
for path in self.sigs.recovery_paths().values() {
for (fg, _) in path.signed_pubkeys.keys() {
for fg in path.signed_pubkeys.keys() {
signers.insert(*fg);
}
}

View File

@ -230,12 +230,10 @@ fn ledger_version_supported(version: Option<&Version>) -> bool {
}
}
pub async fn list_unregistered_hardware_wallets(
aliases: Option<&HashMap<Fingerprint, String>>,
) -> Vec<HardwareWallet> {
pub async fn list_unregistered_hardware_wallets() -> Vec<HardwareWallet> {
let mut hws: Vec<HardwareWallet> = Vec::new();
match specter::SpecterSimulator::try_connect().await {
Ok(device) => match HardwareWallet::new(Arc::new(device), aliases).await {
Ok(device) => match HardwareWallet::new(Arc::new(device), None).await {
Ok(hw) => hws.push(hw),
Err(e) => {
debug!("{}", e);
@ -249,7 +247,7 @@ pub async fn list_unregistered_hardware_wallets(
match specter::Specter::enumerate().await {
Ok(devices) => {
for device in devices {
match HardwareWallet::new(Arc::new(device), aliases).await {
match HardwareWallet::new(Arc::new(device), None).await {
Ok(hw) => hws.push(hw),
Err(e) => {
debug!("{}", e);
@ -270,7 +268,7 @@ pub async fn list_unregistered_hardware_wallets(
device: Arc::new(device),
version,
registered: None,
alias: aliases.and_then(|aliases| aliases.get(&fingerprint).cloned()),
alias: None,
});
} else {
hws.push(HardwareWallet::Unsupported {
@ -310,8 +308,7 @@ pub async fn list_unregistered_hardware_wallets(
device: Arc::new(device),
version,
registered: None,
alias: aliases
.and_then(|aliases| aliases.get(&fingerprint).cloned()),
alias: None,
});
} else {
hws.push(HardwareWallet::Unsupported {

View File

@ -78,6 +78,7 @@ pub enum ImportKeyModal {
EditName,
NameEdited(String),
ConfirmXpub,
SelectKey(usize),
}
#[derive(Debug, Clone)]

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@ use iced::widget::{
};
use iced::{alignment, Alignment, Length};
use async_hwi::DeviceKind;
use std::{collections::HashSet, str::FromStr};
use liana::miniscript::bitcoin::{self, bip32::Fingerprint};
@ -1139,12 +1140,10 @@ pub fn undefined_descriptor_key<'a>() -> Element<'a, message::DefineKey> {
.into()
}
pub fn defined_descriptor_key(
name: &str,
valid: bool,
duplicate_key: bool,
pub fn defined_descriptor_key<'a>(
name: String,
duplicate_name: bool,
) -> Element<message::DefineKey> {
) -> Element<'a, message::DefineKey> {
let col = Column::new()
.width(Length::Fill)
.align_items(Alignment::Center)
@ -1182,33 +1181,7 @@ pub fn defined_descriptor_key(
)
.push(Space::with_height(Length::Fixed(5.0)));
if !valid {
Column::new()
.align_items(Alignment::Center)
.push(
card::invalid(col)
.padding(5)
.height(Length::Fixed(150.0))
.width(Length::Fixed(150.0)),
)
.push(
text("Key is for a different network")
.small()
.style(color::RED),
)
.into()
} else if duplicate_key {
Column::new()
.align_items(Alignment::Center)
.push(
card::invalid(col)
.padding(5)
.height(Length::Fixed(150.0))
.width(Length::Fixed(150.0)),
)
.push(text("Duplicate key").small().style(color::RED))
.into()
} else if duplicate_name {
if duplicate_name {
Column::new()
.align_items(Alignment::Center)
.push(
@ -1231,9 +1204,9 @@ pub fn defined_descriptor_key(
#[allow(clippy::too_many_arguments)]
pub fn edit_key_modal<'a>(
network: bitcoin::Network,
hws: &'a [HardwareWallet],
hws: Vec<Element<'a, Message>>,
keys: Vec<Element<'a, Message>>,
error: Option<&Error>,
processing: bool,
chosen_signer: Option<Fingerprint>,
hot_signer_fingerprint: &Fingerprint,
signer_alias: Option<&'a String>,
@ -1262,21 +1235,12 @@ pub fn edit_key_modal<'a>(
),
)
.spacing(10)
.push(hws.iter().enumerate().fold(
Column::new().spacing(10),
|col, (i, hw)| {
col.push(hw_list_view(
i,
hw,
hw.fingerprint() == chosen_signer,
processing,
!processing
&& hw.fingerprint() == chosen_signer
&& form_xpub.valid
&& !form_xpub.value.is_empty(),
))
},
))
.push(
Column::with_children(hws).spacing(10)
)
.push(
Column::with_children(keys).spacing(10)
)
.push(
Button::new(if Some(*hot_signer_fingerprint) == chosen_signer {
hw::selected_hot_signer(hot_signer_fingerprint, signer_alias)
@ -1312,7 +1276,6 @@ pub fn edit_key_modal<'a>(
.padding(10),
)
.spacing(10)
.push(Container::new(text("/<0;1>/*")).padding(5)),
),
)
.push(
@ -1475,7 +1438,7 @@ pub fn edit_sequence_modal<'a>(sequence: &form::Value<String>) -> Element<'a, Me
.into()
}
fn hw_list_view(
pub fn hw_list_view(
i: usize,
hw: &HardwareWallet,
chosen: bool,
@ -1513,6 +1476,39 @@ fn hw_list_view(
.into()
}
pub fn key_list_view<'a>(
i: usize,
name: &'a str,
fingerprint: &'a Fingerprint,
kind: Option<&'a DeviceKind>,
chosen: bool,
) -> Element<'a, Message> {
let bttn = Button::new(if chosen {
hw::selected_hardware_wallet(
kind.map(|k| k.to_string()).unwrap_or_else(String::new),
None::<String>,
fingerprint,
Some(name),
)
} else {
hw::supported_hardware_wallet(
kind.map(|k| k.to_string()).unwrap_or_else(String::new),
None::<String>,
fingerprint,
Some(name),
)
})
.style(theme::Button::Border)
.width(Length::Fill)
.on_press(Message::DefineDescriptor(
message::DefineDescriptor::KeyModal(message::ImportKeyModal::SelectKey(i)),
));
Container::new(bttn)
.width(Length::Fill)
.style(theme::Container::Card(theme::Card::Simple))
.into()
}
pub fn backup_mnemonic<'a>(
progress: (usize, usize),
words: &'a [&'static str; 12],