Merge #731: installer: forbid keys with same master fg in same path

70dea710ae4e4427402120cc8f54516d9f2cf9b4 installer: forbid keys with same master fg in same path (edouard)

Pull request description:

  ![2023-10-19T17:59:11,287163921+02:00](https://github.com/wizardsardine/liana/assets/6933020/2a7041fa-8d17-43b0-94a9-3412caebc9cc)
  based on #723

ACKs for top commit:
  edouardparis:
    Self-ACK 70dea710ae4e4427402120cc8f54516d9f2cf9b4

Tree-SHA512: 82ef0cbcdad827ae2df4e15cc86cdb54aab29f959124ad35aee5f3e0ba24e2773279d8be109ee33569681c287dcd066e05df4950ff3a773975546a0991b84000
This commit is contained in:
edouard 2023-10-20 12:07:56 +02:00
commit 65cf5cc884
No known key found for this signature in database
GPG Key ID: E65F7A089C20DC8F
3 changed files with 44 additions and 4 deletions

2
gui/Cargo.lock generated
View File

@ -2113,7 +2113,7 @@ dependencies = [
[[package]]
name = "liana"
version = "2.0.0"
source = "git+https://github.com/wizardsardine/liana?branch=master#605a13d4bab662f832b8fcb0d915eb17d0360c1f"
source = "git+https://github.com/wizardsardine/liana?branch=master#4f2ff1abc0e2700d563f3077eb71c22ef9573e5c"
dependencies = [
"backtrace",
"bip39",

View File

@ -1,4 +1,5 @@
use std::collections::{BTreeMap, HashMap, HashSet};
use std::iter::FromIterator;
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
@ -256,7 +257,15 @@ impl Step for DefineDescriptor {
self.setup_mut().check_for_duplicate();
}
message::DefineKey::Edit => {
let setup = self.setup_mut();
let modal = EditXpubModal::new(
HashSet::from_iter(setup.spending_keys.iter().filter_map(|key| {
if key.is_some() && key != &setup.spending_keys[i] {
*key
} else {
None
}
})),
self.setup_mut().spending_keys[i],
None,
i,
@ -338,8 +347,18 @@ impl Step for DefineDescriptor {
self.setup_mut().check_for_duplicate();
}
message::DefineKey::Edit => {
let setup = self.setup_mut();
let modal = EditXpubModal::new(
self.setup[&self.network].recovery_paths[i].keys[j],
HashSet::from_iter(setup.recovery_paths[i].keys.iter().filter_map(
|key| {
if key.is_some() && key != &setup.recovery_paths[i].keys[j] {
*key
} else {
None
}
},
)),
setup.recovery_paths[i].keys[j],
Some(i),
j,
self.network,
@ -658,6 +677,9 @@ pub struct EditXpubModal {
form_xpub: form::Value<String>,
edit_name: bool,
other_path_keys: HashSet<Fingerprint>,
duplicate_master_fg: bool,
keys: Vec<Key>,
hws: Vec<HardwareWallet>,
hot_signer: Arc<Mutex<Signer>>,
@ -668,6 +690,7 @@ pub struct EditXpubModal {
impl EditXpubModal {
#[allow(clippy::too_many_arguments)]
fn new(
other_path_keys: HashSet<Fingerprint>,
key: Option<Fingerprint>,
path_index: Option<usize>,
key_index: usize,
@ -677,6 +700,7 @@ impl EditXpubModal {
) -> Self {
let hot_signer_fingerprint = hot_signer.lock().unwrap().fingerprint();
Self {
other_path_keys,
form_name: form::Value {
valid: true,
value: key
@ -712,6 +736,7 @@ impl EditXpubModal {
chosen_signer: key.map(|k| (k, None)),
hot_signer_fingerprint,
hot_signer,
duplicate_master_fg: false,
}
}
fn load(&self) -> Command<Message> {
@ -728,6 +753,10 @@ impl DescriptorEditModal for EditXpubModal {
}
fn update(&mut self, message: Message) -> Command<Message> {
// Reset these fields.
// the fonction will setup them again if something is wrong
self.duplicate_master_fg = false;
self.error = None;
match message {
Message::Select(i) => {
if let Some(HardwareWallet::Supported {
@ -862,7 +891,9 @@ impl DescriptorEditModal for EditXpubModal {
let key_index = self.key_index;
let name = self.form_name.value.clone();
let device_kind = self.chosen_signer.and_then(|(_, kind)| kind);
if let Some(path_index) = self.path_index {
if self.other_path_keys.contains(&key.master_fingerprint()) {
self.duplicate_master_fg = true;
} else if let Some(path_index) = self.path_index {
return Command::perform(
async move { (path_index, key_index, key) },
move |(path_index, key_index, key)| {
@ -964,6 +995,7 @@ impl DescriptorEditModal for EditXpubModal {
&self.form_xpub,
&self.form_name,
self.edit_name,
self.duplicate_master_fg,
)
}
}

View File

@ -1295,6 +1295,7 @@ pub fn edit_key_modal<'a>(
form_xpub: &form::Value<String>,
form_name: &'a form::Value<String>,
edit_name: bool,
duplicate_master_fg: bool,
) -> Element<'a, Message> {
Column::new()
.push_maybe(error.map(|e| card::error("Failed to import xpub", e.to_string())))
@ -1411,8 +1412,15 @@ pub fn edit_key_modal<'a>(
Column::new()
},
)
.push_maybe(
if duplicate_master_fg {
Some(text("A single signing device may not be used more than once per path. (It can still be used in other paths.)").style(color::RED))
} else {
None
}
)
.push(
if form_xpub.valid && !form_xpub.value.is_empty() && !form_name.value.is_empty()
if form_xpub.valid && !form_xpub.value.is_empty() && !form_name.value.is_empty() && !duplicate_master_fg
{
button::primary(None, "Apply")
.on_press(Message::DefineDescriptor(