From 8ac642b09c8b5bb467e50f5a8e7e569477aa7631 Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Thu, 4 Apr 2024 14:05:41 +0200 Subject: [PATCH] set default derivation for mnemonic and xprv imports to current keystore derivation --- .../sparrow/control/FileKeystoreImportPane.java | 2 +- .../sparrow/control/MnemonicKeystoreImportPane.java | 12 +++++++++--- .../sparrow/control/XprvKeystoreImportPane.java | 13 ++++++++++--- .../keystoreimport/KeystoreImportController.java | 9 +++++++++ .../keystoreimport/KeystoreImportDialog.java | 13 ++++++++----- .../sparrow/keystoreimport/SwController.java | 4 ++-- .../sparrow/wallet/KeystoreController.java | 8 ++++---- 7 files changed, 43 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/sparrowwallet/sparrow/control/FileKeystoreImportPane.java b/src/main/java/com/sparrowwallet/sparrow/control/FileKeystoreImportPane.java index 05cdc424..36b6eaf6 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/FileKeystoreImportPane.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/FileKeystoreImportPane.java @@ -29,7 +29,7 @@ public class FileKeystoreImportPane extends FileImportPane { } if(requiredDerivation != null && !requiredDerivation.getDerivation().equals(keystore.getKeyDerivation().getDerivation())) { - setError("Incorrect derivation", "This account requires a derivation of " + requiredDerivation.getDerivationPath() + ", but the imported keystore has a derivation of " + keystore.getKeyDerivation().getDerivationPath() + "."); + setError("Incorrect derivation", "This account requires a derivation of " + requiredDerivation.getDerivationPath() + ", but the imported keystore has a derivation of " + KeyDerivation.writePath(keystore.getKeyDerivation().getDerivation()) + "."); } else { EventManager.get().post(new KeystoreImportEvent(keystore)); } diff --git a/src/main/java/com/sparrowwallet/sparrow/control/MnemonicKeystoreImportPane.java b/src/main/java/com/sparrowwallet/sparrow/control/MnemonicKeystoreImportPane.java index b6e90bfa..a4b9deb9 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/MnemonicKeystoreImportPane.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/MnemonicKeystoreImportPane.java @@ -33,6 +33,7 @@ import java.util.Optional; public class MnemonicKeystoreImportPane extends MnemonicKeystorePane { protected final Wallet wallet; private final KeystoreMnemonicImport importer; + private final KeyDerivation defaultDerivation; private SplitMenuButton importButton; @@ -43,10 +44,11 @@ public class MnemonicKeystoreImportPane extends MnemonicKeystorePane { private Button confirmButton; private List generatedMnemonicCode; - public MnemonicKeystoreImportPane(Wallet wallet, KeystoreMnemonicImport importer) { + public MnemonicKeystoreImportPane(Wallet wallet, KeystoreMnemonicImport importer, KeyDerivation defaultDerivation) { super(importer.getName(), "Create or enter seed", importer.getKeystoreImportDescription(), "image/" + importer.getWalletModel().getType() + ".png"); this.wallet = wallet; this.importer = importer; + this.defaultDerivation = defaultDerivation; createImportButton(); buttonBox.getChildren().add(importButton); @@ -59,7 +61,7 @@ public class MnemonicKeystoreImportPane extends MnemonicKeystorePane { importButton.getStyleClass().add("default-button"); importButton.setOnAction(event -> { importButton.setDisable(true); - importKeystore(wallet.getScriptType().getDefaultDerivation(), false); + importKeystore(getDefaultDerivation(), false); }); String[] accounts = new String[] {"Import Default Account #0", "Import Account #1", "Import Account #2", "Import Account #3", "Import Account #4", "Import Account #5", "Import Account #6", "Import Account #7", "Import Account #8", "Import Account #9"}; int scriptAccountsLength = ScriptType.P2SH.equals(wallet.getScriptType()) ? 1 : accounts.length; @@ -77,6 +79,10 @@ public class MnemonicKeystoreImportPane extends MnemonicKeystorePane { importButton.setVisible(false); } + private List getDefaultDerivation() { + return defaultDerivation == null || defaultDerivation.getDerivation().isEmpty() ? wallet.getScriptType().getDefaultDerivation() : defaultDerivation.getDerivation(); + } + protected void enterMnemonic(int numWords) { generatedMnemonicCode = null; super.enterMnemonic(numWords); @@ -243,7 +249,7 @@ public class MnemonicKeystoreImportPane extends MnemonicKeystorePane { setDescription("Ready to import"); showHideLink.setText("Show Derivation..."); showHideLink.setVisible(false); - setContent(getDerivationEntry(wallet.getScriptType().getDefaultDerivation())); + setContent(getDerivationEntry(getDefaultDerivation())); } } diff --git a/src/main/java/com/sparrowwallet/sparrow/control/XprvKeystoreImportPane.java b/src/main/java/com/sparrowwallet/sparrow/control/XprvKeystoreImportPane.java index ffe20fa2..71f5f50f 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/XprvKeystoreImportPane.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/XprvKeystoreImportPane.java @@ -28,16 +28,18 @@ import java.util.List; public class XprvKeystoreImportPane extends TitledDescriptionPane { protected final Wallet wallet; protected final KeystoreXprvImport importer; + protected final KeyDerivation defaultDerivation; private Button enterXprvButton; private SplitMenuButton importButton; private ExtendedKey xprv; - public XprvKeystoreImportPane(Wallet wallet, KeystoreXprvImport importer) { + public XprvKeystoreImportPane(Wallet wallet, KeystoreXprvImport importer, KeyDerivation defaultDerivation) { super(importer.getName(), "Extended key import", importer.getKeystoreImportDescription(), "image/" + importer.getWalletModel().getType() + ".png"); this.wallet = wallet; this.importer = importer; + this.defaultDerivation = defaultDerivation; createImportButton(); buttonBox.getChildren().add(importButton); @@ -47,6 +49,7 @@ public class XprvKeystoreImportPane extends TitledDescriptionPane { super("Master Private Key", "BIP32 key", "", "image/" + WalletModel.SEED.getType() + ".png"); this.wallet = null; this.importer = null; + this.defaultDerivation = keystore.getKeyDerivation(); try { this.xprv = keystore.getExtendedMasterPrivateKey(); @@ -79,7 +82,7 @@ public class XprvKeystoreImportPane extends TitledDescriptionPane { importButton.getStyleClass().add("default-button"); importButton.setOnAction(event -> { importButton.setDisable(true); - importKeystore(wallet.getScriptType().getDefaultDerivation()); + importKeystore(getDefaultDerivation()); }); String[] accounts = new String[] {"Import Default Account #0", "Import Account #1", "Import Account #2", "Import Account #3", "Import Account #4", "Import Account #5", "Import Account #6", "Import Account #7", "Import Account #8", "Import Account #9"}; int scriptAccountsLength = ScriptType.P2SH.equals(wallet.getScriptType()) ? 1 : accounts.length; @@ -97,6 +100,10 @@ public class XprvKeystoreImportPane extends TitledDescriptionPane { importButton.setVisible(false); } + private List getDefaultDerivation() { + return defaultDerivation == null || defaultDerivation.getDerivation().isEmpty() ? wallet.getScriptType().getDefaultDerivation() : defaultDerivation.getDerivation(); + } + private void enterXprv() { setDescription("Enter master private key"); showHideLink.setVisible(false); @@ -149,7 +156,7 @@ public class XprvKeystoreImportPane extends TitledDescriptionPane { importButton.setVisible(true); setDescription("Ready to import"); xprv = ExtendedKey.fromDescriptor(xprvField.getText()); - setContent(getDerivationEntry(wallet.getScriptType().getDefaultDerivation())); + setContent(getDerivationEntry(getDefaultDerivation())); }); xprvField.textProperty().addListener((observable, oldValue, newValue) -> { diff --git a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportController.java b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportController.java index fea1b0b4..49700468 100644 --- a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportController.java +++ b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportController.java @@ -31,6 +31,7 @@ public class KeystoreImportController implements Initializable { @FXML private StackPane importPane; + private KeyDerivation defaultDerivation; private KeyDerivation requiredDerivation; private WalletModel requiredModel; @@ -110,6 +111,14 @@ public class KeystoreImportController implements Initializable { } } + public KeyDerivation getDefaultDerivation() { + return defaultDerivation; + } + + public void setDefaultDerivation(KeyDerivation defaultDerivation) { + this.defaultDerivation = defaultDerivation; + } + public KeyDerivation getRequiredDerivation() { return requiredDerivation; } diff --git a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportDialog.java b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportDialog.java index 76fb48d7..cbc49191 100644 --- a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportDialog.java @@ -29,7 +29,7 @@ public class KeystoreImportDialog extends Dialog { this(wallet, initialSource, null, null, false); } - public KeystoreImportDialog(Wallet wallet, KeystoreSource initialSource, KeyDerivation requiredDerivation, WalletModel requiredModel, boolean restrictSource) { + public KeystoreImportDialog(Wallet wallet, KeystoreSource initialSource, KeyDerivation currentDerivation, WalletModel currentModel, boolean restrictImport) { EventManager.get().register(this); setOnCloseRequest(event -> { EventManager.get().unregister(this); @@ -43,12 +43,15 @@ public class KeystoreImportDialog extends Dialog { dialogPane.setContent(Borders.wrap(ksiLoader.load()).emptyBorder().buildAll()); keystoreImportController = ksiLoader.getController(); keystoreImportController.initializeView(wallet); - keystoreImportController.selectSource(initialSource, restrictSource); - keystoreImportController.setRequiredDerivation(requiredDerivation); - keystoreImportController.setRequiredModel(requiredModel); + keystoreImportController.selectSource(initialSource, restrictImport); + keystoreImportController.setDefaultDerivation(currentDerivation); + if(restrictImport) { + keystoreImportController.setRequiredDerivation(currentDerivation); + keystoreImportController.setRequiredModel(currentModel); + } final ButtonType watchOnlyButtonType = new javafx.scene.control.ButtonType(Network.get().getXpubHeader().getDisplayName() + " / Watch Only Wallet", ButtonBar.ButtonData.LEFT); - if(!restrictSource) { + if(!restrictImport) { dialogPane.getButtonTypes().add(watchOnlyButtonType); } final ButtonType cancelButtonType = new javafx.scene.control.ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE); diff --git a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/SwController.java b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/SwController.java index de008a3e..035630c9 100644 --- a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/SwController.java +++ b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/SwController.java @@ -27,9 +27,9 @@ public class SwController extends KeystoreImportDetailController { if(importer instanceof KeystoreFileImport) { importPane = new FileKeystoreImportPane(getMasterController().getWallet(), (KeystoreFileImport)importer, getMasterController().getRequiredDerivation()); } else if(importer instanceof KeystoreMnemonicImport) { - importPane = new MnemonicKeystoreImportPane(getMasterController().getWallet(), (KeystoreMnemonicImport)importer); + importPane = new MnemonicKeystoreImportPane(getMasterController().getWallet(), (KeystoreMnemonicImport)importer, getMasterController().getDefaultDerivation()); } else if(importer instanceof KeystoreXprvImport) { - importPane = new XprvKeystoreImportPane(getMasterController().getWallet(), (KeystoreXprvImport)importer); + importPane = new XprvKeystoreImportPane(getMasterController().getWallet(), (KeystoreXprvImport)importer, getMasterController().getDefaultDerivation()); } else { throw new IllegalArgumentException("Could not create ImportPane for importer of type " + importer.getClass()); } diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/KeystoreController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/KeystoreController.java index 8dc50a8b..6351a43f 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/KeystoreController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/KeystoreController.java @@ -367,10 +367,10 @@ public class KeystoreController extends WalletFormController implements Initiali } private void launchImportDialog(KeystoreSource initialSource) { - boolean restrictSource = keystore.getSource() != KeystoreSource.SW_WATCH && keystoreSourceToggleGroup.getToggles().stream().anyMatch(toggle -> ((ToggleButton)toggle).isDisabled()); - KeyDerivation requiredDerivation = restrictSource ? keystore.getKeyDerivation() : null; - WalletModel requiredModel = restrictSource ? keystore.getWalletModel() : null; - KeystoreImportDialog dlg = new KeystoreImportDialog(getWalletForm().getWallet(), initialSource, requiredDerivation, requiredModel, restrictSource); + boolean restrictImport = keystore.getSource() != KeystoreSource.SW_WATCH && keystoreSourceToggleGroup.getToggles().stream().anyMatch(toggle -> ((ToggleButton)toggle).isDisabled()); + KeyDerivation currentDerivation = keystore.getKeyDerivation(); + WalletModel currentModel = keystore.getWalletModel(); + KeystoreImportDialog dlg = new KeystoreImportDialog(getWalletForm().getWallet(), initialSource, currentDerivation, currentModel, restrictImport); dlg.initOwner(selectSourcePane.getScene().getWindow()); Optional result = dlg.showAndWait(); if(result.isPresent()) {