diff --git a/lark b/lark index 33fbba95..13001e8a 160000 --- a/lark +++ b/lark @@ -1 +1 @@ -Subproject commit 33fbba951e3a881a96a71f4711777dbc69f9c0ab +Subproject commit 13001e8acf7048a15c81cc050c65e6e164c3aa33 diff --git a/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java b/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java index 6e5afda8..4ad9117b 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java @@ -378,11 +378,6 @@ public class DevicePane extends TitledDescriptionPane { }); displayAddressButton.managedProperty().bind(displayAddressButton.visibleProperty()); displayAddressButton.setVisible(false); - - List fingerprints = outputDescriptor.getExtendedPublicKeys().stream().map(extKey -> outputDescriptor.getKeyDerivation(extKey).getMasterFingerprint()).collect(Collectors.toList()); - if(device.getFingerprint() != null && !fingerprints.contains(device.getFingerprint())) { - displayAddressButton.setDisable(true); - } } private void createSignMessageButton() { @@ -394,10 +389,6 @@ public class DevicePane extends TitledDescriptionPane { }); signMessageButton.managedProperty().bind(signMessageButton.visibleProperty()); signMessageButton.setVisible(false); - - if(device.getFingerprint() != null && !device.getFingerprint().equals(requiredDerivation.getMasterFingerprint())) { - signMessageButton.setDisable(true); - } } private void createDiscoverKeystoresButton() { @@ -629,11 +620,26 @@ public class DevicePane extends TitledDescriptionPane { setPassphraseButton.setDisable(true); setContent(getPassphraseEntry()); setExpanded(true); + } else if(device.getFingerprint() == null && (deviceOperation.equals(DeviceOperation.DISPLAY_ADDRESS) || deviceOperation.equals(DeviceOperation.SIGN_MESSAGE) + || deviceOperation.equals(DeviceOperation.DISCOVER_KEYSTORES))) { + //A PIN protected device reports no fingerprint until it is unlocked, and these operations gate on it to avoid using the wrong device + Hwi.EnumerateService enumerateService = new Hwi.EnumerateService(passphrase.get()); + enumerateService.setOnSucceeded(enumerateEvent -> { + for(Device freshDevice : enumerateService.getValue()) { + if(device.getPath().equals(freshDevice.getPath()) && device.getModel().equals(freshDevice.getModel())) { + device.setFingerprint(freshDevice.getFingerprint()); + } + } + + showUnlockedOperation(); + }); + enumerateService.setOnFailed(enumerateEvent -> { + showUnlockedOperation(); + setError("Error", enumerateService.getException().getMessage()); + }); + enumerateService.start(); } else { - showOperationButton(); - if(!deviceOperation.equals(DeviceOperation.IMPORT)) { - setContent(getTogglePassphraseOn()); - } + showUnlockedOperation(); } } else { setError("Incorrect PIN", null); @@ -652,6 +658,13 @@ public class DevicePane extends TitledDescriptionPane { sendPinService.start(); } + private void showUnlockedOperation() { + showOperationButton(); + if(!deviceOperation.equals(DeviceOperation.IMPORT)) { + setContent(getTogglePassphraseOn()); + } + } + private void sendPassphrase(String passphrase) { Hwi.EnumerateService enumerateService = new Hwi.EnumerateService(passphrase); enumerateService.setOnSucceeded(workerStateEvent -> { @@ -1193,16 +1206,23 @@ public class DevicePane extends TitledDescriptionPane { signButton.setVisible(true); showHideLink.setVisible(false); } else if(deviceOperation.equals(DeviceOperation.DISPLAY_ADDRESS)) { + //A device which has not yet been unlocked reports no fingerprint, so this check is only meaningful once the operation button is shown + List fingerprints = outputDescriptor.getExtendedPublicKeys().stream().map(extKey -> outputDescriptor.getKeyDerivation(extKey).getMasterFingerprint()).collect(Collectors.toList()); displayAddressButton.setDefaultButton(defaultDevice); displayAddressButton.setVisible(true); + displayAddressButton.setDisable(device.getFingerprint() != null && !fingerprints.contains(device.getFingerprint())); showHideLink.setVisible(false); } else if(deviceOperation.equals(DeviceOperation.SIGN_MESSAGE)) { signMessageButton.setDefaultButton(defaultDevice); signMessageButton.setVisible(true); + signMessageButton.setDisable(device.getFingerprint() != null && !device.getFingerprint().equals(requiredDerivation.getMasterFingerprint())); showHideLink.setVisible(false); } else if(deviceOperation.equals(DeviceOperation.DISCOVER_KEYSTORES)) { + //Discovery stamps the wallet master fingerprint on keystores built from the device xpubs, so a mismatched device is silently persisted discoverKeystoresButton.setDefaultButton(defaultDevice); discoverKeystoresButton.setVisible(true); + discoverKeystoresButton.setDisable(device.getFingerprint() != null && wallet.getKeystores().size() == 1 + && !device.getFingerprint().equals(wallet.getKeystores().get(0).getKeyDerivation().getMasterFingerprint())); showHideLink.setVisible(false); } else if(deviceOperation.equals(DeviceOperation.GET_PRIVATE_KEY)) { if(defaultDevice) {