From 8efee4eaae8998f4c55c5403e68d6c117f5d6f2f Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Tue, 25 Nov 2025 09:43:43 +0200 Subject: [PATCH] pass default derivation to usb device and card import panes --- .../sparrow/control/CardImportPane.java | 13 ++++- .../sparrow/control/DevicePane.java | 49 ++++++++++++------- .../sparrow/control/WalletImportDialog.java | 2 +- .../keystoreimport/HwAirgappedController.java | 2 +- .../HwUsbDevicesController.java | 2 +- .../keystoreimport/KeystoreImportDialog.java | 8 --- 6 files changed, 45 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/sparrowwallet/sparrow/control/CardImportPane.java b/src/main/java/com/sparrowwallet/sparrow/control/CardImportPane.java index 03ea3994..92d7f0d2 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/CardImportPane.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/CardImportPane.java @@ -3,6 +3,7 @@ package com.sparrowwallet.sparrow.control; import com.google.common.base.Throwables; import com.sparrowwallet.drongo.KeyDerivation; import com.sparrowwallet.drongo.crypto.ChildNumber; +import com.sparrowwallet.drongo.protocol.ScriptType; import com.sparrowwallet.drongo.protocol.Sha256Hash; import com.sparrowwallet.drongo.wallet.*; import com.sparrowwallet.sparrow.AppServices; @@ -47,10 +48,18 @@ public class CardImportPane extends TitledDescriptionPane { protected Button importButton; private final SimpleStringProperty pin = new SimpleStringProperty(""); - public CardImportPane(Wallet wallet, KeystoreCardImport importer, KeyDerivation requiredDerivation) { + public CardImportPane(Wallet wallet, KeystoreCardImport importer, KeyDerivation defaultDerivation, KeyDerivation requiredDerivation) { super(importer.getName(), "Place card on reader", importer.getKeystoreImportDescription(getAccount(wallet, requiredDerivation)), importer.getWalletModel()); this.importer = importer; - this.derivation = requiredDerivation == null ? wallet.getScriptType().getDefaultDerivation() : requiredDerivation.getDerivation(); + this.derivation = requiredDerivation == null ? getDefaultDerivation(wallet, defaultDerivation) : requiredDerivation.getDerivation(); + } + + private static List getDefaultDerivation(Wallet wallet, KeyDerivation defaultDerivation) { + if(defaultDerivation != null && !defaultDerivation.getDerivation().isEmpty()) { + return defaultDerivation.getDerivation(); + } + + return wallet == null || wallet.getScriptType() == null ? ScriptType.P2WPKH.getDefaultDerivation() : wallet.getScriptType().getDefaultDerivation(); } @Override diff --git a/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java b/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java index a1ee7421..cd82c548 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java @@ -51,7 +51,8 @@ public class DevicePane extends TitledDescriptionPane { private final Wallet wallet; private final PSBT psbt; private final OutputDescriptor outputDescriptor; - private final KeyDerivation keyDerivation; + private final KeyDerivation defaultDerivation; + private final KeyDerivation requiredDerivation; private final String message; private final List availableAccounts; private final Device device; @@ -74,13 +75,14 @@ public class DevicePane extends TitledDescriptionPane { private boolean defaultDevice; - public DevicePane(Wallet wallet, Device device, boolean defaultDevice, KeyDerivation requiredDerivation) { + public DevicePane(Wallet wallet, Device device, boolean defaultDevice, KeyDerivation defaultDerivation, KeyDerivation requiredDerivation) { super(device.getModel().toDisplayString(), "", "", device.getModel()); this.deviceOperation = DeviceOperation.IMPORT; this.wallet = wallet; this.psbt = null; this.outputDescriptor = null; - this.keyDerivation = requiredDerivation; + this.defaultDerivation = defaultDerivation; + this.requiredDerivation = requiredDerivation; this.message = null; this.availableAccounts = null; this.device = device; @@ -107,7 +109,8 @@ public class DevicePane extends TitledDescriptionPane { this.wallet = wallet; this.psbt = psbt; this.outputDescriptor = null; - this.keyDerivation = null; + this.defaultDerivation = null; + this.requiredDerivation = null; this.message = null; this.availableAccounts = null; this.device = device; @@ -134,7 +137,8 @@ public class DevicePane extends TitledDescriptionPane { this.wallet = wallet; this.psbt = null; this.outputDescriptor = outputDescriptor; - this.keyDerivation = null; + this.defaultDerivation = null; + this.requiredDerivation = null; this.message = null; this.availableAccounts = null; this.device = device; @@ -151,13 +155,14 @@ public class DevicePane extends TitledDescriptionPane { buttonBox.getChildren().addAll(setPassphraseButton, displayAddressButton); } - public DevicePane(Wallet wallet, String message, KeyDerivation keyDerivation, Device device, boolean defaultDevice) { + public DevicePane(Wallet wallet, String message, KeyDerivation requiredDerivation, Device device, boolean defaultDevice) { super(device.getModel().toDisplayString(), "", "", device.getModel()); this.deviceOperation = DeviceOperation.SIGN_MESSAGE; this.wallet = wallet; this.psbt = null; this.outputDescriptor = null; - this.keyDerivation = keyDerivation; + this.defaultDerivation = requiredDerivation; + this.requiredDerivation = requiredDerivation; this.message = message; this.availableAccounts = null; this.device = device; @@ -184,7 +189,8 @@ public class DevicePane extends TitledDescriptionPane { this.wallet = wallet; this.psbt = null; this.outputDescriptor = null; - this.keyDerivation = null; + this.defaultDerivation = null; + this.requiredDerivation = null; this.message = null; this.device = device; this.defaultDevice = defaultDevice; @@ -207,7 +213,8 @@ public class DevicePane extends TitledDescriptionPane { this.wallet = null; this.psbt = null; this.outputDescriptor = null; - this.keyDerivation = null; + this.defaultDerivation = null; + this.requiredDerivation = null; this.message = null; this.device = device; this.defaultDevice = defaultDevice; @@ -286,13 +293,12 @@ public class DevicePane extends TitledDescriptionPane { } private void createImportButton() { - importButton = keyDerivation == null ? new SplitMenuButton() : new Button(); + importButton = requiredDerivation == null ? new SplitMenuButton() : new Button(); importButton.setAlignment(Pos.CENTER_RIGHT); importButton.setText("Import Keystore"); importButton.setOnAction(event -> { importButton.setDisable(true); - List defaultDerivation = wallet.getScriptType() == null ? ScriptType.P2WPKH.getDefaultDerivation() : wallet.getScriptType().getDefaultDerivation(); - importKeystore(keyDerivation == null ? defaultDerivation : keyDerivation.getDerivation()); + importKeystore(requiredDerivation == null ? getDefaultDerivation() : requiredDerivation.getDerivation()); }); if(importButton instanceof SplitMenuButton importMenuButton) { @@ -363,7 +369,7 @@ public class DevicePane extends TitledDescriptionPane { signMessageButton.managedProperty().bind(signMessageButton.visibleProperty()); signMessageButton.setVisible(false); - if(device.getFingerprint() != null && !device.getFingerprint().equals(keyDerivation.getMasterFingerprint())) { + if(device.getFingerprint() != null && !device.getFingerprint().equals(requiredDerivation.getMasterFingerprint())) { signMessageButton.setDisable(true); } } @@ -433,6 +439,14 @@ public class DevicePane extends TitledDescriptionPane { getAddressButton.setVisible(false); } + private List getDefaultDerivation() { + if(defaultDerivation != null && !defaultDerivation.getDerivation().isEmpty()) { + return defaultDerivation.getDerivation(); + } + + return wallet == null || wallet.getScriptType() == null ? ScriptType.P2WPKH.getDefaultDerivation() : wallet.getScriptType().getDefaultDerivation(); + } + private void unlock(Device device) { if(device.getModel().requiresPinPrompt()) { promptPin(); @@ -864,7 +878,7 @@ public class DevicePane extends TitledDescriptionPane { if(device.isCard()) { try { CardApi cardApi = CardApi.getCardApi(device.getModel(), pin.get()); - Service signMessageService = cardApi.getSignMessageService(message, wallet.getScriptType(), keyDerivation.getDerivation(), messageProperty); + Service signMessageService = cardApi.getSignMessageService(message, wallet.getScriptType(), requiredDerivation.getDerivation(), messageProperty); handleCardOperation(signMessageService, signMessageButton, "Signing", true, event -> { String signature = signMessageService.getValue(); EventManager.get().post(new MessageSignedEvent(wallet, signature)); @@ -875,7 +889,7 @@ public class DevicePane extends TitledDescriptionPane { signButton.setDisable(false); } } else { - Hwi.SignMessageService signMessageService = new Hwi.SignMessageService(device, passphrase.get(), message, keyDerivation.getDerivationPath()); + Hwi.SignMessageService signMessageService = new Hwi.SignMessageService(device, passphrase.get(), message, requiredDerivation.getDerivationPath()); signMessageService.setOnSucceeded(successEvent -> { String signature = signMessageService.getValue(); EventManager.get().post(new MessageSignedEvent(wallet, signature)); @@ -1003,8 +1017,7 @@ public class DevicePane extends TitledDescriptionPane { importButton.setVisible(true); showHideLink.setText("Show derivation..."); showHideLink.setVisible(!device.isCard()); - List defaultDerivation = wallet.getScriptType() == null ? ScriptType.P2WPKH.getDefaultDerivation() : wallet.getScriptType().getDefaultDerivation(); - setContent(getDerivationEntry(keyDerivation == null ? defaultDerivation : keyDerivation.getDerivation())); + setContent(getDerivationEntry(requiredDerivation == null ? getDefaultDerivation() : requiredDerivation.getDerivation())); } else if(deviceOperation.equals(DeviceOperation.SIGN)) { signButton.setDefaultButton(defaultDevice); signButton.setVisible(true); @@ -1038,7 +1051,7 @@ public class DevicePane extends TitledDescriptionPane { TextField derivationField = new TextField(); derivationField.setPromptText("Derivation path"); derivationField.setText(KeyDerivation.writePath(derivation)); - derivationField.setDisable(device.isCard() || keyDerivation != null); + derivationField.setDisable(device.isCard() || requiredDerivation != null); HBox.setHgrow(derivationField, Priority.ALWAYS); ValidationSupport validationSupport = new ValidationSupport(); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java index 207418fd..dcdef393 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java @@ -112,7 +112,7 @@ public class WalletImportDialog extends Dialog { List devices = enumerateService.getValue(); importAccordion.getPanes().removeIf(titledPane -> titledPane instanceof DevicePane); for(Device device : devices) { - DevicePane devicePane = new DevicePane(new Wallet(), device, devices.size() == 1, null); + DevicePane devicePane = new DevicePane(new Wallet(), device, devices.size() == 1, null, null); importAccordion.getPanes().add(0, devicePane); } Platform.runLater(() -> EventManager.get().post(new UsbDeviceEvent(devices))); diff --git a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwAirgappedController.java b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwAirgappedController.java index f18588d5..063e0281 100644 --- a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwAirgappedController.java +++ b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwAirgappedController.java @@ -43,7 +43,7 @@ public class HwAirgappedController extends KeystoreImportDetailController { List cardImporters = List.of(new Tapsigner(), new Satochip(), new Satschip()); for(KeystoreCardImport importer : cardImporters) { if(!importer.isDeprecated() || Config.get().isShowDeprecatedImportExport()) { - CardImportPane importPane = new CardImportPane(getMasterController().getWallet(), importer, getMasterController().getRequiredDerivation()); + CardImportPane importPane = new CardImportPane(getMasterController().getWallet(), importer, getMasterController().getDefaultDerivation(), getMasterController().getRequiredDerivation()); if(getMasterController().getRequiredModel() == null || getMasterController().getRequiredModel() == importer.getWalletModel()) { importAccordion.getPanes().add(importPane); } diff --git a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwUsbDevicesController.java b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwUsbDevicesController.java index c99f9a9b..b1743c08 100644 --- a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwUsbDevicesController.java +++ b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwUsbDevicesController.java @@ -13,7 +13,7 @@ public class HwUsbDevicesController extends KeystoreImportDetailController { public void initializeView(List devices) { for(Device device : devices) { - DevicePane devicePane = new DevicePane(getMasterController().getWallet(), device, devices.size() == 1, getMasterController().getRequiredDerivation()); + DevicePane devicePane = new DevicePane(getMasterController().getWallet(), device, devices.size() == 1, getMasterController().getDefaultDerivation(), getMasterController().getRequiredDerivation()); if(getMasterController().getRequiredModel() == null || getMasterController().getRequiredModel() == device.getModel()) { deviceAccordion.getPanes().add(devicePane); } diff --git a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportDialog.java b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportDialog.java index 14c322f7..cacbb824 100644 --- a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportDialog.java @@ -25,14 +25,6 @@ public class KeystoreImportDialog extends Dialog { private final ScriptType scriptType; private final String existingLabel; - public KeystoreImportDialog(Wallet wallet) { - this(wallet, KeystoreSource.HW_USB); - } - - public KeystoreImportDialog(Wallet wallet, KeystoreSource initialSource) { - this(wallet, initialSource, null, null, Keystore.DEFAULT_LABEL, false); - } - public KeystoreImportDialog(Wallet wallet, KeystoreSource initialSource, KeyDerivation currentDerivation, WalletModel currentModel, String currentLabel, boolean restrictImport) { EventManager.get().register(this); setOnCloseRequest(event -> {