improve sp related output descriptor and psbt behaviour

This commit is contained in:
Craig Raw 2026-04-24 12:37:07 +02:00
parent 0bb5e9319f
commit c23dbeedcf
9 changed files with 46 additions and 14 deletions

2
drongo

@ -1 +1 @@
Subproject commit 854eb513e9212e6d1e7662e20833d9fda00573b6
Subproject commit 9c28138cd37694f612d5e1dbca70f9833f9584d7

View File

@ -75,7 +75,11 @@ public abstract class BaseController {
builder.append(keystore.getKeyDerivation().getMasterFingerprint());
builder.append(KeyDerivation.writePath(KeyDerivation.parsePath(keystore.getKeyDerivation().getDerivationPath())).substring(1));
builder.append("]");
builder.append(keystore.getExtendedPublicKey().toString());
if(keystore.getExtendedPublicKey() != null) {
builder.append(keystore.getExtendedPublicKey().toString());
} else if(keystore.getSilentPaymentScanAddress() != null) {
builder.append(keystore.getSilentPaymentScanAddress().toKeyString());
}
return builder.toString();
}

View File

@ -691,7 +691,7 @@ public class QRScanDialog extends Dialog<QRScanDialog.Result> {
KeyDerivation keyDerivation = getKeyDerivation(urhdKey.getOrigin());
if(urhdKey.getChainCode() == null) {
ECKey ecKey = getKey(urhdKey);
source = source.replaceAll("@" + i, OutputDescriptor.writeKey(ecKey, keyDerivation, true));
source = source.replaceAll("@" + i, OutputDescriptor.writeKey(ecKey, keyDerivation, true, true));
} else {
ExtendedKey extendedKey = getExtendedKey(urhdKey);
source = source.replaceAll("@" + i, OutputDescriptor.writeKey(extendedKey, keyDerivation, null, true, true));

View File

@ -851,8 +851,7 @@ public class TransactionDiagram extends GridPane {
actionBox.setAlignment(Pos.CENTER_LEFT);
SilentPayment silentPayment = spChangeOutput.getSilentPayment();
SilentPaymentAddress spAddress = silentPayment.getSilentPaymentAddress();
String changeDesc = spAddress.toString().substring(0, 8) + "...";
Label changeLabel = new Label(changeDesc, getChangeGlyph());
Label changeLabel = new Label("Change", getChangeGlyph());
changeLabel.getStyleClass().addAll("output-label", "change-label");
changeLabel.setSkin(new AddressLabelSkin(changeLabel));
Tooltip changeTooltip = new Tooltip("Change of " + getCoinValue(silentPayment.getAmount()) + "\n" + spAddress);

View File

@ -31,8 +31,19 @@ public class Descriptor implements WalletImport, WalletExport {
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
if(wallet.getPolicyType() == PolicyType.SINGLE_SP) {
OutputDescriptor outputDescriptor = OutputDescriptor.getOutputDescriptor(wallet);
bufferedWriter.write("# Single argument descriptor:");
bufferedWriter.newLine();
bufferedWriter.write(outputDescriptor.toString(true));
bufferedWriter.newLine();
bufferedWriter.newLine();
bufferedWriter.write("# Two argument descriptor:");
bufferedWriter.newLine();
bufferedWriter.write(outputDescriptor.toString(true, true, true, true));
bufferedWriter.newLine();
} else {
bufferedWriter.write("# Receive and change descriptor:");
bufferedWriter.newLine();

View File

@ -6,6 +6,7 @@ import com.sparrowwallet.drongo.KeyDerivation;
import com.sparrowwallet.drongo.KeyPurpose;
import com.sparrowwallet.drongo.OutputDescriptor;
import com.sparrowwallet.drongo.Utils;
import com.sparrowwallet.drongo.policy.PolicyType;
import com.sparrowwallet.drongo.protocol.*;
import com.sparrowwallet.drongo.wallet.*;
import com.sparrowwallet.sparrow.AppServices;
@ -68,7 +69,11 @@ public class WalletLabels implements WalletImport, WalletExport {
for(Keystore keystore : exportWallet.getKeystores()) {
if(keystore.getLabel() != null && !keystore.getLabel().isEmpty()) {
labels.add(new Label(Type.xpub, keystore.getExtendedPublicKey().toString(), keystore.getLabel(), null, null));
if(exportWallet.getPolicyType() == PolicyType.SINGLE_SP && keystore.getSilentPaymentScanAddress() != null) {
labels.add(new Label(Type.spscan, keystore.getSilentPaymentScanAddress().toKeyString(), keystore.getLabel(), null, null));
} else if(keystore.getExtendedPublicKey() != null) {
labels.add(new Label(Type.xpub, keystore.getExtendedPublicKey().toString(), keystore.getLabel(), null, null));
}
}
}
@ -220,7 +225,17 @@ public class WalletLabels implements WalletImport, WalletExport {
if(label.type == Type.xpub) {
for(Keystore keystore : wallet.getKeystores()) {
if(keystore.getExtendedPublicKey().toString().equals(label.ref)) {
if(keystore.getExtendedPublicKey() != null && keystore.getExtendedPublicKey().toString().equals(label.ref)) {
keystore.setLabel(label.label);
List<Keystore> changedKeystores = changedWalletKeystores.computeIfAbsent(wallet, w -> new ArrayList<>());
changedKeystores.add(keystore);
}
}
}
if(label.type == Type.spscan) {
for(Keystore keystore : wallet.getKeystores()) {
if(keystore.getSilentPaymentScanAddress() != null && keystore.getSilentPaymentScanAddress().toKeyString().equals(label.ref)) {
keystore.setLabel(label.label);
List<Keystore> changedKeystores = changedWalletKeystores.computeIfAbsent(wallet, w -> new ArrayList<>());
changedKeystores.add(keystore);
@ -432,7 +447,7 @@ public class WalletLabels implements WalletImport, WalletExport {
}
private enum Type {
tx, addr, pubkey, input, output, xpub
tx, addr, pubkey, input, output, xpub, spscan
}
private static class Label {

View File

@ -26,9 +26,9 @@ public class HwAirgappedController extends KeystoreImportDetailController {
public void initializeView() {
List<KeystoreFileImport> fileImporters = Collections.emptyList();
if(getMasterController().getWallet().getPolicyType().equals(PolicyType.SINGLE)) {
if(getMasterController().getWallet().getPolicyType().equals(PolicyType.SINGLE_HD)) {
fileImporters = List.of(new ColdcardSinglesig(), new CoboVaultSinglesig(), new Jade(), new KeystoneSinglesig(), new PassportSinglesig(), new SeedSigner(), new GordianSeedTool(), new SpecterDIY(), new Krux(), new AirGapVault(), new KeycardShellSinglesig());
} else if(getMasterController().getWallet().getPolicyType().equals(PolicyType.MULTI)) {
} else if(getMasterController().getWallet().getPolicyType().equals(PolicyType.MULTI_HD)) {
fileImporters = List.of(new Bip129(), new ColdcardMultisig(), new CoboVaultMultisig(), new JadeMultisig(), new KeystoneMultisig(), new PassportMultisig(), new SeedSigner(), new GordianSeedTool(), new SpecterDIY(), new Krux(), new KeycardShellMultisig());
}
@ -41,7 +41,10 @@ public class HwAirgappedController extends KeystoreImportDetailController {
}
}
List<KeystoreCardImport> cardImporters = List.of(new Tapsigner(), new Satochip(), new Satschip(), new Keycard());
List<KeystoreCardImport> cardImporters = Collections.emptyList();
if(getMasterController().getWallet().getPolicyType().equals(PolicyType.SINGLE_HD) || getMasterController().getWallet().getPolicyType().equals(PolicyType.MULTI_HD)) {
cardImporters = List.of(new Tapsigner(), new Satochip(), new Satschip(), new Keycard());
}
for(KeystoreCardImport importer : cardImporters) {
if(!importer.isDeprecated() || Config.get().isShowDeprecatedImportExport()) {
CardImportPane importPane = new CardImportPane(getMasterController().getWallet(), importer, getMasterController().getDefaultDerivation(), getMasterController().getRequiredDerivation());

View File

@ -760,8 +760,8 @@ public class KeystoreController extends WalletFormController implements Initiali
public void keystoreLabelsChanged(KeystoreLabelsChangedEvent event) {
if(event.getWalletId().equals(walletForm.getWalletId())) {
for(Keystore changedKeystore : event.getChangedKeystores()) {
if(xpub.getText().trim().equals(changedKeystore.getExtendedPublicKey().toString()) && !label.getText().equals(changedKeystore.getLabel())
|| spScan.getText().trim().equals(changedKeystore.getSilentPaymentScanAddress().toKeyString()) && !label.getText().equals(changedKeystore.getLabel())) {
if((changedKeystore.getExtendedPublicKey() != null && xpub.getText().trim().equals(changedKeystore.getExtendedPublicKey().toString()) && !label.getText().equals(changedKeystore.getLabel()))
|| (changedKeystore.getSilentPaymentScanAddress() != null && spScan.getText().trim().equals(changedKeystore.getSilentPaymentScanAddress().toKeyString()) && !label.getText().equals(changedKeystore.getLabel()))) {
label.textProperty().removeListener(labelChangeListener);
label.setText(changedKeystore.getLabel());
keystore.setLabel(changedKeystore.getLabel());

View File

@ -924,7 +924,7 @@ public class SettingsController extends WalletFormController implements Initiali
List<Keystore> importedKeystores = event.getImportedWallet().getKeystores();
List<Keystore> nonWatchKeystores = walletForm.getWallet().getKeystores().stream().filter(k -> k.isValid() && k.getSource() != KeystoreSource.SW_WATCH).collect(Collectors.toList());
for(Keystore nonWatchKeystore : nonWatchKeystores) {
Optional<Keystore> optReplacedKeystore = importedKeystores.stream().filter(k -> nonWatchKeystore.getExtendedPublicKey().equals(k.getExtendedPublicKey())).findFirst();
Optional<Keystore> optReplacedKeystore = importedKeystores.stream().filter(k -> Objects.equals(nonWatchKeystore.getExtendedPublicKey(), k.getExtendedPublicKey())).findFirst();
if(optReplacedKeystore.isPresent()) {
int index = importedKeystores.indexOf(optReplacedKeystore.get());
importedKeystores.remove(index);