set default derivation for mnemonic and xprv imports to current keystore derivation

This commit is contained in:
Craig Raw 2024-04-04 14:05:41 +02:00
parent 33d9f260c4
commit 8ac642b09c
7 changed files with 43 additions and 18 deletions

View file

@ -29,7 +29,7 @@ public class FileKeystoreImportPane extends FileImportPane {
} }
if(requiredDerivation != null && !requiredDerivation.getDerivation().equals(keystore.getKeyDerivation().getDerivation())) { 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 { } else {
EventManager.get().post(new KeystoreImportEvent(keystore)); EventManager.get().post(new KeystoreImportEvent(keystore));
} }

View file

@ -33,6 +33,7 @@ import java.util.Optional;
public class MnemonicKeystoreImportPane extends MnemonicKeystorePane { public class MnemonicKeystoreImportPane extends MnemonicKeystorePane {
protected final Wallet wallet; protected final Wallet wallet;
private final KeystoreMnemonicImport importer; private final KeystoreMnemonicImport importer;
private final KeyDerivation defaultDerivation;
private SplitMenuButton importButton; private SplitMenuButton importButton;
@ -43,10 +44,11 @@ public class MnemonicKeystoreImportPane extends MnemonicKeystorePane {
private Button confirmButton; private Button confirmButton;
private List<String> generatedMnemonicCode; private List<String> 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"); super(importer.getName(), "Create or enter seed", importer.getKeystoreImportDescription(), "image/" + importer.getWalletModel().getType() + ".png");
this.wallet = wallet; this.wallet = wallet;
this.importer = importer; this.importer = importer;
this.defaultDerivation = defaultDerivation;
createImportButton(); createImportButton();
buttonBox.getChildren().add(importButton); buttonBox.getChildren().add(importButton);
@ -59,7 +61,7 @@ public class MnemonicKeystoreImportPane extends MnemonicKeystorePane {
importButton.getStyleClass().add("default-button"); importButton.getStyleClass().add("default-button");
importButton.setOnAction(event -> { importButton.setOnAction(event -> {
importButton.setDisable(true); 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"}; 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; int scriptAccountsLength = ScriptType.P2SH.equals(wallet.getScriptType()) ? 1 : accounts.length;
@ -77,6 +79,10 @@ public class MnemonicKeystoreImportPane extends MnemonicKeystorePane {
importButton.setVisible(false); importButton.setVisible(false);
} }
private List<ChildNumber> getDefaultDerivation() {
return defaultDerivation == null || defaultDerivation.getDerivation().isEmpty() ? wallet.getScriptType().getDefaultDerivation() : defaultDerivation.getDerivation();
}
protected void enterMnemonic(int numWords) { protected void enterMnemonic(int numWords) {
generatedMnemonicCode = null; generatedMnemonicCode = null;
super.enterMnemonic(numWords); super.enterMnemonic(numWords);
@ -243,7 +249,7 @@ public class MnemonicKeystoreImportPane extends MnemonicKeystorePane {
setDescription("Ready to import"); setDescription("Ready to import");
showHideLink.setText("Show Derivation..."); showHideLink.setText("Show Derivation...");
showHideLink.setVisible(false); showHideLink.setVisible(false);
setContent(getDerivationEntry(wallet.getScriptType().getDefaultDerivation())); setContent(getDerivationEntry(getDefaultDerivation()));
} }
} }

View file

@ -28,16 +28,18 @@ import java.util.List;
public class XprvKeystoreImportPane extends TitledDescriptionPane { public class XprvKeystoreImportPane extends TitledDescriptionPane {
protected final Wallet wallet; protected final Wallet wallet;
protected final KeystoreXprvImport importer; protected final KeystoreXprvImport importer;
protected final KeyDerivation defaultDerivation;
private Button enterXprvButton; private Button enterXprvButton;
private SplitMenuButton importButton; private SplitMenuButton importButton;
private ExtendedKey xprv; 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"); super(importer.getName(), "Extended key import", importer.getKeystoreImportDescription(), "image/" + importer.getWalletModel().getType() + ".png");
this.wallet = wallet; this.wallet = wallet;
this.importer = importer; this.importer = importer;
this.defaultDerivation = defaultDerivation;
createImportButton(); createImportButton();
buttonBox.getChildren().add(importButton); buttonBox.getChildren().add(importButton);
@ -47,6 +49,7 @@ public class XprvKeystoreImportPane extends TitledDescriptionPane {
super("Master Private Key", "BIP32 key", "", "image/" + WalletModel.SEED.getType() + ".png"); super("Master Private Key", "BIP32 key", "", "image/" + WalletModel.SEED.getType() + ".png");
this.wallet = null; this.wallet = null;
this.importer = null; this.importer = null;
this.defaultDerivation = keystore.getKeyDerivation();
try { try {
this.xprv = keystore.getExtendedMasterPrivateKey(); this.xprv = keystore.getExtendedMasterPrivateKey();
@ -79,7 +82,7 @@ public class XprvKeystoreImportPane extends TitledDescriptionPane {
importButton.getStyleClass().add("default-button"); importButton.getStyleClass().add("default-button");
importButton.setOnAction(event -> { importButton.setOnAction(event -> {
importButton.setDisable(true); 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"}; 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; int scriptAccountsLength = ScriptType.P2SH.equals(wallet.getScriptType()) ? 1 : accounts.length;
@ -97,6 +100,10 @@ public class XprvKeystoreImportPane extends TitledDescriptionPane {
importButton.setVisible(false); importButton.setVisible(false);
} }
private List<ChildNumber> getDefaultDerivation() {
return defaultDerivation == null || defaultDerivation.getDerivation().isEmpty() ? wallet.getScriptType().getDefaultDerivation() : defaultDerivation.getDerivation();
}
private void enterXprv() { private void enterXprv() {
setDescription("Enter master private key"); setDescription("Enter master private key");
showHideLink.setVisible(false); showHideLink.setVisible(false);
@ -149,7 +156,7 @@ public class XprvKeystoreImportPane extends TitledDescriptionPane {
importButton.setVisible(true); importButton.setVisible(true);
setDescription("Ready to import"); setDescription("Ready to import");
xprv = ExtendedKey.fromDescriptor(xprvField.getText()); xprv = ExtendedKey.fromDescriptor(xprvField.getText());
setContent(getDerivationEntry(wallet.getScriptType().getDefaultDerivation())); setContent(getDerivationEntry(getDefaultDerivation()));
}); });
xprvField.textProperty().addListener((observable, oldValue, newValue) -> { xprvField.textProperty().addListener((observable, oldValue, newValue) -> {

View file

@ -31,6 +31,7 @@ public class KeystoreImportController implements Initializable {
@FXML @FXML
private StackPane importPane; private StackPane importPane;
private KeyDerivation defaultDerivation;
private KeyDerivation requiredDerivation; private KeyDerivation requiredDerivation;
private WalletModel requiredModel; 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() { public KeyDerivation getRequiredDerivation() {
return requiredDerivation; return requiredDerivation;
} }

View file

@ -29,7 +29,7 @@ public class KeystoreImportDialog extends Dialog<Keystore> {
this(wallet, initialSource, null, null, false); 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); EventManager.get().register(this);
setOnCloseRequest(event -> { setOnCloseRequest(event -> {
EventManager.get().unregister(this); EventManager.get().unregister(this);
@ -43,12 +43,15 @@ public class KeystoreImportDialog extends Dialog<Keystore> {
dialogPane.setContent(Borders.wrap(ksiLoader.load()).emptyBorder().buildAll()); dialogPane.setContent(Borders.wrap(ksiLoader.load()).emptyBorder().buildAll());
keystoreImportController = ksiLoader.getController(); keystoreImportController = ksiLoader.getController();
keystoreImportController.initializeView(wallet); keystoreImportController.initializeView(wallet);
keystoreImportController.selectSource(initialSource, restrictSource); keystoreImportController.selectSource(initialSource, restrictImport);
keystoreImportController.setRequiredDerivation(requiredDerivation); keystoreImportController.setDefaultDerivation(currentDerivation);
keystoreImportController.setRequiredModel(requiredModel); 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); 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); dialogPane.getButtonTypes().add(watchOnlyButtonType);
} }
final ButtonType cancelButtonType = new javafx.scene.control.ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE); final ButtonType cancelButtonType = new javafx.scene.control.ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);

View file

@ -27,9 +27,9 @@ public class SwController extends KeystoreImportDetailController {
if(importer instanceof KeystoreFileImport) { if(importer instanceof KeystoreFileImport) {
importPane = new FileKeystoreImportPane(getMasterController().getWallet(), (KeystoreFileImport)importer, getMasterController().getRequiredDerivation()); importPane = new FileKeystoreImportPane(getMasterController().getWallet(), (KeystoreFileImport)importer, getMasterController().getRequiredDerivation());
} else if(importer instanceof KeystoreMnemonicImport) { } 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) { } else if(importer instanceof KeystoreXprvImport) {
importPane = new XprvKeystoreImportPane(getMasterController().getWallet(), (KeystoreXprvImport)importer); importPane = new XprvKeystoreImportPane(getMasterController().getWallet(), (KeystoreXprvImport)importer, getMasterController().getDefaultDerivation());
} else { } else {
throw new IllegalArgumentException("Could not create ImportPane for importer of type " + importer.getClass()); throw new IllegalArgumentException("Could not create ImportPane for importer of type " + importer.getClass());
} }

View file

@ -367,10 +367,10 @@ public class KeystoreController extends WalletFormController implements Initiali
} }
private void launchImportDialog(KeystoreSource initialSource) { private void launchImportDialog(KeystoreSource initialSource) {
boolean restrictSource = keystore.getSource() != KeystoreSource.SW_WATCH && keystoreSourceToggleGroup.getToggles().stream().anyMatch(toggle -> ((ToggleButton)toggle).isDisabled()); boolean restrictImport = keystore.getSource() != KeystoreSource.SW_WATCH && keystoreSourceToggleGroup.getToggles().stream().anyMatch(toggle -> ((ToggleButton)toggle).isDisabled());
KeyDerivation requiredDerivation = restrictSource ? keystore.getKeyDerivation() : null; KeyDerivation currentDerivation = keystore.getKeyDerivation();
WalletModel requiredModel = restrictSource ? keystore.getWalletModel() : null; WalletModel currentModel = keystore.getWalletModel();
KeystoreImportDialog dlg = new KeystoreImportDialog(getWalletForm().getWallet(), initialSource, requiredDerivation, requiredModel, restrictSource); KeystoreImportDialog dlg = new KeystoreImportDialog(getWalletForm().getWallet(), initialSource, currentDerivation, currentModel, restrictImport);
dlg.initOwner(selectSourcePane.getScene().getWindow()); dlg.initOwner(selectSourcePane.getScene().getWindow());
Optional<Keystore> result = dlg.showAndWait(); Optional<Keystore> result = dlg.showAndWait();
if(result.isPresent()) { if(result.isPresent()) {