initial policy type related changes from drongo
What changed, and why it matters
This commit is a large but mechanical rename in the Sparrow Wallet codebase. It replaces the old policy type constants `PolicyType.SINGLE` and `PolicyType.MULTI` with more specific names `PolicyType.SINGLE_HD` and `PolicyType.MULTI_HD`, and adds handling for a new `PolicyType.SINGLE_SILENT_PAYMENTS`. It also updates method calls in the underlying `drongo` library to pass the policy type explicitly. There is no direct evidence in the diff of a security vulnerability being fixed; it reads like preparation for adding silent-payment wallet support. A few import cleanups and one new guard against exporting silent-payment wallets are included.
Treat this as a routine feature/refactoring commit rather than a security patch. Reviewers should verify that the new `SINGLE_SILENT_PAYMENTS` policy type is handled consistently in all code paths (especially signing, export, and address derivation) and that the updated `drongo` dependency does not introduce behavioral changes beyond the enum rename. Run the updated unit tests and perform regression testing on wallet import/export and signing flows.
Security signals we found
Large enum rename across wallet import/export, signing, and address derivation paths
New policy type `SINGLE_SILENT_PAYMENTS` introduced with limited exporter support
Message signing now explicitly restricted to HD single-sig wallets
ElectrumPersonalServer export now throws for silent-payment wallets
Storage layer now conditionally handles `silentPaymentScanAddress`
Evidence from the diff
The patch updates 31 files to align with a drongo library API change that splits PolicyType.SINGLE into SINGLE_HD/SINGLE_SILENT_PAYMENTS and PolicyType.MULTI into MULTI_HD. Most changes are simple enum replacements and passing PolicyType into ScriptType.getAddress(), getOutputKey(), and addSpendingInput(). Notable additions: WalletExportDialog now has a branch for SINGLE_SILENT_PAYMENTS; ElectrumPersonalServer now rejects silent-payment exports; Storage conditionally copies silentPaymentScanAddress; MessageSignDialog now rejects non-HD single-sig wallets for message signing; BaseController and SettingsDialog treat SINGLE_SILENT_PAYMENTS like SINGLE for UI purposes. No cryptographic, input-validation, or memory-safety fixes are visible.
Changed components
Wallet policy type handling (AppController, AppServices, BaseController, SettingsDialog)Hardware/device wallet import (DevicePane, CkCardApi)File/mnemonic keystore import (FileWalletKeystoreImportPane, MnemonicWalletKeystoreImportPane, Bip39Dialog, WatchOnlyDialog)Wallet export (WalletExportDialog, CaravanMultisig, ColdcardMultisig, Electrum, ElectrumPersonalServer, CoboVaultSinglesig, ColdcardSinglesig, KeystoneSinglesig)Message and transaction signing (MessageSignDialog, PrivateKeySweepDialog, LnurlAuth, VersionCheckService)Transaction UI (HeadersController, PaymentController)Wallet storage (Storage)Unit testsInspect captured patch +96 / −88
diff --git a/src/main/java/com/sparrowwallet/sparrow/AppController.java b/src/main/java/com/sparrowwallet/sparrow/AppController.java
index d6fec7e..3f972f6 100644
--- a/src/main/java/com/sparrowwallet/sparrow/AppController.java
+++ b/src/main/java/com/sparrowwallet/sparrow/AppController.java
@@ -1121,7 +1121,7 @@ public class AppController implements Initializable {
WalletNameDialog.NameAndBirthDate nameAndBirthDate = optNameAndBirthDate.get();
File walletFile = Storage.getWalletFile(nameAndBirthDate.getName());
Storage storage = new Storage(walletFile);
- Wallet wallet = new Wallet(nameAndBirthDate.getName(), PolicyType.SINGLE, ScriptType.P2WPKH, nameAndBirthDate.getBirthDate());
+ Wallet wallet = new Wallet(nameAndBirthDate.getName(), PolicyType.SINGLE_HD, ScriptType.P2WPKH, nameAndBirthDate.getBirthDate());
addWalletTabOrWindow(storage, wallet, false);
}
}
@@ -1271,7 +1271,7 @@ public class AppController implements Initializable {
List<ExtendedKey> xpubs = wallet.getKeystores().stream().map(Keystore::getExtendedPublicKey).collect(Collectors.toList());
Optional<WalletForm> optNewWalletForm = walletTabData.stream()
.map(WalletTabData::getWalletForm)
- .filter(wf -> wf.getSettingsWalletForm() != null && wf.getSettingsWalletForm().getWallet().getPolicyType() == PolicyType.MULTI &&
+ .filter(wf -> wf.getSettingsWalletForm() != null && wf.getSettingsWalletForm().getWallet().getPolicyType() == PolicyType.MULTI_HD &&
wf.getSettingsWalletForm().getWallet().getScriptType() == wallet.getScriptType() && !wf.getSettingsWalletForm().getWallet().isValid() &&
wf.getSettingsWalletForm().getWallet().getKeystores().stream().map(Keystore::getExtendedPublicKey).anyMatch(xpubs::contains)).findFirst();
if(optNewWalletForm.isPresent()) {
diff --git a/src/main/java/com/sparrowwallet/sparrow/AppServices.java b/src/main/java/com/sparrowwallet/sparrow/AppServices.java
index ec4fafb..b0a111b 100644
--- a/src/main/java/com/sparrowwallet/sparrow/AppServices.java
+++ b/src/main/java/com/sparrowwallet/sparrow/AppServices.java
@@ -1077,7 +1077,7 @@ public class AppServices {
try {
Auth47 auth47 = new Auth47(uri);
List<ScriptType> scriptTypes = PaymentCode.SEGWIT_SCRIPT_TYPES;
- Wallet wallet = selectWallet(List.of(PolicyType.SINGLE), scriptTypes, false, true, "login to " + auth47.getCallback().getHost(), true);
+ Wallet wallet = selectWallet(List.of(PolicyType.SINGLE_HD), scriptTypes, false, true, "login to " + auth47.getCallback().getHost(), true);
if(wallet != null) {
try {
@@ -1097,8 +1097,8 @@ public class AppServices {
private static void openLnurlAuthUri(URI uri) {
try {
LnurlAuth lnurlAuth = new LnurlAuth(uri);
- List<ScriptType> scriptTypes = ScriptType.getAddressableScriptTypes(PolicyType.SINGLE);
- Wallet wallet = selectWallet(List.of(PolicyType.SINGLE), scriptTypes, true, true, lnurlAuth.getLoginMessage(), true);
+ List<ScriptType> scriptTypes = ScriptType.getAddressableScriptTypes(PolicyType.SINGLE_HD);
+ Wallet wallet = selectWallet(List.of(PolicyType.SINGLE_HD), scriptTypes, true, true, lnurlAuth.getLoginMessage(), true);
if(wallet != null) {
if(wallet.isEncrypted()) {
diff --git a/src/main/java/com/sparrowwallet/sparrow/BaseController.java b/src/main/java/com/sparrowwallet/sparrow/BaseController.java
index 7263ef2..cee2d97 100644
--- a/src/main/java/com/sparrowwallet/sparrow/BaseController.java
+++ b/src/main/java/com/sparrowwallet/sparrow/BaseController.java
@@ -55,7 +55,8 @@ public abstract class BaseController {
descriptorArea.setMouseOverTextDelay(Duration.ofMillis(150));
descriptorArea.addEventHandler(MouseOverTextEvent.MOUSE_OVER_TEXT_BEGIN, e -> {
TwoDimensional.Position position = descriptorArea.getParagraph(0).getStyleSpans().offsetToPosition(e.getCharacterIndex(), Backward);
- int index = descriptorArea.getWallet().getPolicyType() == PolicyType.SINGLE ? position.getMajor() - 1 : ((position.getMajor() - 1) / 2);
+ int index = descriptorArea.getWallet().getPolicyType() == PolicyType.SINGLE || descriptorArea.getWallet().getPolicyType() == PolicyType.SINGLE_SILENT_PAYMENTS ?
+ position.getMajor() - 1 : ((position.getMajor() - 1) / 2);
if(position.getMajor() > 0 && index >= 0 && index < descriptorArea.getWallet().getKeystores().size()) {
Keystore hoverKeystore = descriptorArea.getWallet().getKeystores().get(index);
Point2D pos = e.getScreenPosition();
diff --git a/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java b/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java
index 0a5d98c..06ca959 100644
--- a/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java
+++ b/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java
@@ -775,10 +775,10 @@ public class DevicePane extends TitledDescriptionPane {
if(wallet.getScriptType() == null) {
ScriptType scriptType = Arrays.stream(ScriptType.ADDRESSABLE_TYPES).filter(type -> type.getDefaultDerivation().get(0).equals(derivation.get(0))).findFirst().orElse(ScriptType.P2PKH);
wallet.setName(device.getModel().toDisplayString());
- wallet.setPolicyType(PolicyType.SINGLE);
+ wallet.setPolicyType(PolicyType.SINGLE_HD);
wallet.setScriptType(scriptType);
wallet.getKeystores().add(keystore);
- wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, scriptType, wallet.getKeystores(), null));
+ wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, scriptType, wallet.getKeystores(), null));
EventManager.get().post(new WalletImportEvent(wallet));
} else {
@@ -926,7 +926,7 @@ public class DevicePane extends TitledDescriptionPane {
List<StandardAccount> discoveryAccounts = new ArrayList<>(Arrays.asList(StandardAccount.values()).subList(0, optRange.get() + 1));
Map<Hwi.WalletType, String> derivationPaths = new LinkedHashMap<>();
- List<ScriptType> scriptTypes = new ArrayList<>(ScriptType.getAddressableScriptTypes(PolicyType.SINGLE));
+ List<ScriptType> scriptTypes = new ArrayList<>(ScriptType.getAddressableScriptTypes(PolicyType.SINGLE_HD));
if(device.getModel() == WalletModel.BITBOX_02) {
scriptTypes.remove(ScriptType.P2PKH);
}
@@ -943,7 +943,7 @@ public class DevicePane extends TitledDescriptionPane {
for(Map.Entry<Hwi.WalletType, String> entry : accountXpubs.entrySet()) {
try {
Wallet wallet = new Wallet(device.getModel().toDisplayString());
- wallet.setPolicyType(PolicyType.SINGLE);
+ wallet.setPolicyType(PolicyType.SINGLE_HD);
wallet.setScriptType(entry.getKey().scriptType());
Keystore keystore = new Keystore();
keystore.setLabel(device.getModel().toDisplayString());
@@ -952,7 +952,7 @@ public class DevicePane extends TitledDescriptionPane {
keystore.setKeyDerivation(new KeyDerivation(device.getFingerprint(), derivationPaths.get(entry.getKey())));
keystore.setExtendedPublicKey(ExtendedKey.fromDescriptor(entry.getValue()));
wallet.getKeystores().add(keystore);
- wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, entry.getKey().scriptType(), wallet.getKeystores(), 1));
+ wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, entry.getKey().scriptType(), wallet.getKeystores(), 1));
if(entry.getKey().standardAccount().equals(StandardAccount.ACCOUNT_0)) {
wallets.add(wallet);
} else {
diff --git a/src/main/java/com/sparrowwallet/sparrow/control/FileWalletKeystoreImportPane.java b/src/main/java/com/sparrowwallet/sparrow/control/FileWalletKeystoreImportPane.java
index c1a0e1b..ca0be68 100644
--- a/src/main/java/com/sparrowwallet/sparrow/control/FileWalletKeystoreImportPane.java
+++ b/src/main/java/com/sparrowwallet/sparrow/control/FileWalletKeystoreImportPane.java
@@ -50,12 +50,12 @@ public class FileWalletKeystoreImportPane extends FileImportPane {
this.fileName = fileName;
this.password = password;
- List<ScriptType> scriptTypes = ScriptType.getAddressableScriptTypes(PolicyType.SINGLE);
+ List<ScriptType> scriptTypes = ScriptType.getAddressableScriptTypes(PolicyType.SINGLE_HD);
if(wallets != null && !wallets.isEmpty()) {
if(wallets.size() == 1 && scriptTypes.contains(wallets.get(0).getScriptType())) {
Wallet wallet = wallets.get(0);
- wallet.setPolicyType(PolicyType.SINGLE);
- wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, wallet.getScriptType(), wallet.getKeystores(), null));
+ wallet.setPolicyType(PolicyType.SINGLE_HD);
+ wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, wallet.getScriptType(), wallet.getKeystores(), null));
wallet.setName(importer.getName());
EventManager.get().post(new WalletImportEvent(wallets.get(0)));
} else {
@@ -81,8 +81,8 @@ public class FileWalletKeystoreImportPane extends FileImportPane {
if(wallets != null && !wallets.isEmpty()) {
Wallet wallet = wallets.stream().filter(wallet1 -> wallet1.getScriptType() == scriptType).findFirst().orElseThrow(ImportException::new);
wallet.setName(importer.getName());
- wallet.setPolicyType(PolicyType.SINGLE);
- wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, wallet.getScriptType(), wallet.getKeystores(), null));
+ wallet.setPolicyType(PolicyType.SINGLE_HD);
+ wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, wallet.getScriptType(), wallet.getKeystores(), null));
EventManager.get().post(new WalletImportEvent(wallet));
} else {
ByteArrayInputStream bais = new ByteArrayInputStream(fileBytes);
@@ -90,10 +90,10 @@ public class FileWalletKeystoreImportPane extends FileImportPane {
Wallet wallet = new Wallet();
wallet.setName(Files.getNameWithoutExtension(fileName));
- wallet.setPolicyType(PolicyType.SINGLE);
+ wallet.setPolicyType(PolicyType.SINGLE_HD);
wallet.setScriptType(scriptType);
wallet.getKeystores().add(keystore);
- wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, scriptType, wallet.getKeystores(), null));
+ wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, scriptType, wallet.getKeystores(), null));
EventManager.get().post(new WalletImportEvent(wallet));
}
diff --git a/src/main/java/com/sparrowwallet/sparrow/control/MessageSignDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/MessageSignDialog.java
index 3a6864e..360d333 100644
--- a/src/main/java/com/sparrowwallet/sparrow/control/MessageSignDialog.java
+++ b/src/main/java/com/sparrowwallet/sparrow/control/MessageSignDialog.java
@@ -25,8 +25,6 @@ import com.sparrowwallet.sparrow.io.Storage;
import javafx.application.Platform;
import javafx.scene.Node;
import javafx.scene.control.*;
-import javafx.scene.image.Image;
-import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
@@ -297,8 +295,8 @@ public class MessageSignDialog extends Dialog<ButtonBar.ButtonData> {
}
private void checkWalletSigning(Wallet wallet) {
- if(wallet.getKeystores().size() != 1) {
- throw new IllegalArgumentException("Cannot sign messages using a wallet with multiple keystores - a single key is required");
+ if(wallet.getKeystores().size() != 1 || wallet.getPolicyType() != PolicyType.SINGLE_HD) {
+ throw new IllegalArgumentException("Cannot sign messages using a non-HD wallet or a wallet with multiple keystores");
}
}
@@ -323,7 +321,7 @@ public class MessageSignDialog extends Dialog<ButtonBar.ButtonData> {
private boolean isValidAddress() {
try {
Address address = getAddress();
- return address.getScriptType().isAllowed(PolicyType.SINGLE) || address.getScriptType() == ScriptType.P2SH;
+ return address.getScriptType().isAllowed(PolicyType.SINGLE_HD) || address.getScriptType() == ScriptType.P2SH;
} catch (InvalidAddressException e) {
return false;
}
@@ -466,11 +464,11 @@ public class MessageSignDialog extends Dialog<ButtonBar.ButtonData> {
if(scriptType == ScriptType.P2SH) {
scriptType = ScriptType.P2SH_P2WPKH;
}
- if(!ScriptType.getScriptTypesForPolicyType(PolicyType.SINGLE).contains(scriptType)) {
+ if(!ScriptType.getScriptTypesForPolicyType(PolicyType.SINGLE_HD).contains(scriptType)) {
throw new IllegalArgumentException("Only single signature P2PKH, P2SH-P2WPKH or P2WPKH addresses can verify messages.");
}
- Address signedMessageAddress = scriptType.getAddress(signedMessageKey);
+ Address signedMessageAddress = scriptType.getAddress(PolicyType.SINGLE_HD, signedMessageKey);
return providedAddress.equals(signedMessageAddress);
}
@@ -527,7 +525,7 @@ public class MessageSignDialog extends Dialog<ButtonBar.ButtonData> {
psbtInput.setTapInternalKey(pubKey);
psbtInput.getTapDerivedPublicKeys().put(ECKey.fromPublicOnly(pubKey.getPubKeyXCoord()), Map.of(fullDerivation, Collections.emptyList()));
} else {
- psbtInput.getDerivedPublicKeys().put(scriptType.getOutputKey(pubKey), fullDerivation);
+ psbtInput.getDerivedPublicKeys().put(scriptType.getOutputKey(signingWallet.getPolicyType(), pubKey), fullDerivation);
}
}
diff --git a/src/main/java/com/sparrowwallet/sparrow/control/MnemonicWalletKeystoreImportPane.java b/src/main/java/com/sparrowwallet/sparrow/control/MnemonicWalletKeystoreImportPane.java
index 494f8eb..b361eaf 100644
--- a/src/main/java/com/sparrowwallet/sparrow/control/MnemonicWalletKeystoreImportPane.java
+++ b/src/main/java/com/sparrowwallet/sparrow/control/MnemonicWalletKeystoreImportPane.java
@@ -108,11 +108,11 @@ public class MnemonicWalletKeystoreImportPane extends MnemonicKeystorePane {
discoverButton.setGraphic(progressIndicator);
List<Wallet> wallets = new ArrayList<>();
- List<List<ChildNumber>> derivations = ScriptType.getScriptTypesForPolicyType(PolicyType.SINGLE).stream().map(ScriptType::getDefaultDerivation).collect(Collectors.toList());
+ List<List<ChildNumber>> derivations = ScriptType.getScriptTypesForPolicyType(PolicyType.SINGLE_HD).stream().map(ScriptType::getDefaultDerivation).collect(Collectors.toList());
derivations.add(List.of(new ChildNumber(0, true)));
derivations.add(ScriptType.P2PKH.getDefaultDerivation(1)); //Bisq segwit misderivation
- for(ScriptType scriptType : ScriptType.getScriptTypesForPolicyType(PolicyType.SINGLE)) {
+ for(ScriptType scriptType : ScriptType.getScriptTypesForPolicyType(PolicyType.SINGLE_HD)) {
for(List<ChildNumber> derivation : derivations) {
try {
Wallet wallet = getWallet(scriptType, derivation);
@@ -165,11 +165,11 @@ public class MnemonicWalletKeystoreImportPane extends MnemonicKeystorePane {
private Wallet getWallet(ScriptType scriptType, List<ChildNumber> derivation) throws ImportException {
Wallet wallet = new Wallet("");
- wallet.setPolicyType(PolicyType.SINGLE);
+ wallet.setPolicyType(PolicyType.SINGLE_HD);
wallet.setScriptType(scriptType);
Keystore keystore = importer.getKeystore(derivation, wordEntriesProperty.get(), passphraseProperty.get());
wallet.getKeystores().add(keystore);
- wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, scriptType, wallet.getKeystores(), 1));
+ wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, scriptType, wallet.getKeystores(), 1));
return wallet;
}
@@ -178,7 +178,7 @@ public class MnemonicWalletKeystoreImportPane extends MnemonicKeystorePane {
HBox fieldBox = new HBox(5);
fieldBox.setAlignment(Pos.CENTER_RIGHT);
- ComboBox<ScriptType> scriptTypeComboBox = new ComboBox<>(FXCollections.observableArrayList(ScriptType.getAddressableScriptTypes(PolicyType.SINGLE)));
+ ComboBox<ScriptType> scriptTypeComboBox = new ComboBox<>(FXCollections.observableArrayList(ScriptType.getAddressableScriptTypes(PolicyType.SINGLE_HD)));
if(scriptTypeComboBox.getItems().contains(ScriptType.P2WPKH)) {
scriptTypeComboBox.setValue(ScriptType.P2WPKH);
}
diff --git a/src/main/java/com/sparrowwallet/sparrow/control/PrivateKeySweepDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/PrivateKeySweepDialog.java
index 2f0da1b..912d3a8 100644
--- a/src/main/java/com/sparrowwallet/sparrow/control/PrivateKeySweepDialog.java
+++ b/src/main/java/com/sparrowwallet/sparrow/control/PrivateKeySweepDialog.java
@@ -109,7 +109,7 @@ public class PrivateKeySweepDialog extends Dialog<Transaction> {
Field keyScriptTypeField = new Field();
keyScriptTypeField.setText("Script Type:");
keyScriptType = new ComboBox<>();
- keyScriptType.setItems(FXCollections.observableList(ScriptType.getAddressableScriptTypes(PolicyType.SINGLE)));
+ keyScriptType.setItems(FXCollections.observableList(ScriptType.getAddressableScriptTypes(PolicyType.SINGLE_HD)));
keyScriptTypeField.getInputs().add(keyScriptType);
keyScriptType.setConverter(new StringConverter<ScriptType>() {
@@ -287,14 +287,14 @@ public class PrivateKeySweepDialog extends Dialog<Transaction> {
private void setFromAddress() {
DumpedPrivateKey privateKey = getPrivateKey();
ScriptType scriptType = keyScriptType.getValue();
- Address address = scriptType.getAddress(privateKey.getKey());
+ Address address = scriptType.getAddress(PolicyType.SINGLE_HD, privateKey.getKey());
keyAddress.setText(address.toString());
}
private void setScriptTypes(boolean isValidKey) {
boolean compressed = !isValidKey || getPrivateKey().getKey().isCompressed();
- if(compressed && !keyScriptType.getItems().equals(ScriptType.getAddressableScriptTypes(PolicyType.SINGLE))) {
- keyScriptType.getItems().addAll(ScriptType.getAddressableScriptTypes(PolicyType.SINGLE).stream().filter(s -> !keyScriptType.getItems().contains(s)).collect(Collectors.toList()));
+ if(compressed && !keyScriptType.getItems().equals(ScriptType.getAddressableScriptTypes(PolicyType.SINGLE_HD))) {
+ keyScriptType.getItems().addAll(ScriptType.getAddressableScriptTypes(PolicyType.SINGLE_HD).stream().filter(s -> !keyScriptType.getItems().contains(s)).collect(Collectors.toList()));
} else if(!compressed && !keyScriptType.getItems().equals(List.of(ScriptType.P2PKH))) {
keyScriptType.getSelectionModel().select(0);
keyScriptType.getItems().removeIf(scriptType -> scriptType != ScriptType.P2PKH);
@@ -346,7 +346,7 @@ public class PrivateKeySweepDialog extends Dialog<Transaction> {
try {
DumpedPrivateKey privateKey = getPrivateKey();
ScriptType scriptType = keyScriptType.getValue();
- Address fromAddress = scriptType.getAddress(privateKey.getKey());
+ Address fromAddress = scriptType.getAddress(PolicyType.SINGLE_HD, privateKey.getKey());
Address destAddress = getToAddress();
Date since = null;
@@ -389,7 +389,7 @@ public class PrivateKeySweepDialog extends Dialog<Transaction> {
Transaction noFeeTransaction = new Transaction();
long total = 0;
for(TransactionOutput txOutput : txOutputs) {
- scriptType.addSpendingInput(noFeeTransaction, txOutput, pubKey, TransactionSignature.dummy(scriptType == P2TR ? TransactionSignature.Type.SCHNORR : TransactionSignature.Type.ECDSA));
+ scriptType.addSpendingInput(PolicyType.SINGLE_HD, noFeeTransaction, txOutput, pubKey, TransactionSignature.dummy(scriptType == P2TR ? TransactionSignature.Type.SCHNORR : TransactionSignature.Type.ECDSA));
total += txOutput.getValue();
}
@@ -448,7 +448,7 @@ public class PrivateKeySweepDialog extends Dialog<Transaction> {
psbtInput.setWitnessScript(txInput.getWitness().getWitnessScript());
}
- if(!psbtInput.sign(scriptType.getOutputKey(privKey))) {
+ if(!psbtInput.sign(scriptType.getOutputKey(PolicyType.SINGLE_HD, privKey))) {
AppServices.showErrorDialog("Failed to sign", "Failed to sign for transaction output " + utxoOutput.getHash() + ":" + utxoOutput.getIndex());
return;
}
@@ -456,7 +456,7 @@ public class PrivateKeySweepDialog extends Dialog<Transaction> {
TransactionSignature signature = psbtInput.isTaproot() ? psbtInput.getTapKeyPathSignature() : psbtInput.getPartialSignature(pubKey);
Transaction finalizeTransaction = new Transaction();
- TransactionInput finalizedTxInput = scriptType.addSpendingInput(finalizeTransaction, utxoOutput, pubKey, signature);
+ TransactionInput finalizedTxInput = scriptType.addSpendingInput(PolicyType.SINGLE_HD, finalizeTransaction, utxoOutput, pubKey, signature);
psbtInput.setFinalScriptSig(finalizedTxInput.getScriptSig());
psbtInput.setFinalScriptWitness(finalizedTxInput.getWitness());
}
diff --git a/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java
index dc96f8b..82d12a9 100644
--- a/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java
+++ b/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java
@@ -49,6 +49,8 @@ public class WalletExportDialog extends Dialog<Wallet> {
} else if(wallet.getPolicyType() == PolicyType.MULTI) {
exporters = List.of(new Bip129(), new CaravanMultisig(), new ColdcardMultisig(), new CoboVaultMultisig(), new Electrum(), new ElectrumPersonalServer(), new KeystoneMultisig(),
new Descriptor(), new JadeMultisig(), new PassportMultisig(), new SpecterDesktop(), new BlueWalletMultisig(), new SpecterDIY(), new Sparrow(), new WalletLabels(allWalletForms), new WalletTransactions(selectedWalletForm));
+ } else if(wallet.getPolicyType() == PolicyType.SINGLE_SILENT_PAYMENTS) {
+ exporters = List.of(new Sparrow(), new WalletLabels(allWalletForms), new WalletTransactions(selectedWalletForm));
} else {
throw new UnsupportedOperationException("Cannot export wallet with policy type " + wallet.getPolicyType());
}
diff --git a/src/main/java/com/sparrowwallet/sparrow/io/CaravanMultisig.java b/src/main/java/com/sparrowwallet/sparrow/io/CaravanMultisig.java
index 4fe7b9c..e4ceca6 100644
--- a/src/main/java/com/sparrowwallet/sparrow/io/CaravanMultisig.java
+++ b/src/main/java/com/sparrowwallet/sparrow/io/CaravanMultisig.java
@@ -49,7 +49,7 @@ public class CaravanMultisig implements WalletImport, WalletExport {
Wallet wallet = new Wallet();
wallet.setName(cf.name);
- wallet.setPolicyType(PolicyType.MULTI);
+ wallet.setPolicyType(PolicyType.MULTI_HD);
ScriptType scriptType = ScriptType.valueOf(cf.addressType.replace('-', '_'));
for(ExtPublicKey extKey : cf.extendedPublicKeys) {
@@ -80,7 +80,7 @@ public class CaravanMultisig implements WalletImport, WalletExport {
}
wallet.setScriptType(scriptType);
- wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.MULTI, scriptType, wallet.getKeystores(), cf.quorum.requiredSigners));
+ wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.MULTI_HD, scriptType, wallet.getKeystores(), cf.quorum.requiredSigners));
return wallet;
} catch(Exception e) {
@@ -99,7 +99,7 @@ public class CaravanMultisig implements WalletImport, WalletExport {
throw new ExportException("Cannot export an incomplete wallet");
}
- if(!wallet.getPolicyType().equals(PolicyType.MULTI)) {
+ if(!wallet.getPolicyType().equals(PolicyType.MULTI_HD)) {
throw new ExportException(getName() + " import requires a multisig wallet");
}
diff --git a/src/main/java/com/sparrowwallet/sparrow/io/CoboVaultSinglesig.java b/src/main/java/com/sparrowwallet/sparrow/io/CoboVaultSinglesig.java
index 7e302c1..bc50c8e 100644
--- a/src/main/java/com/sparrowwallet/sparrow/io/CoboVaultSinglesig.java
+++ b/src/main/java/com/sparrowwallet/sparrow/io/CoboVaultSinglesig.java
@@ -73,10 +73,10 @@ public class CoboVaultSinglesig implements KeystoreFileImport, WalletImport {
Keystore keystore = getKeystore(ScriptType.P2WPKH, inputStream, "");
Wallet wallet = new Wallet();
- wallet.setPolicyType(PolicyType.SINGLE);
+ wallet.setPolicyType(PolicyType.SINGLE_HD);
wallet.setScriptType(ScriptType.P2WPKH);
wallet.getKeystores().add(keystore);
- wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, wallet.getKeystores(), null));
+ wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, wallet.getKeystores(), null));
try {
wallet.checkWallet();
diff --git a/src/main/java/com/sparrowwallet/sparrow/io/ColdcardMultisig.java b/src/main/java/com/sparrowwallet/sparrow/io/ColdcardMultisig.java
index c21a75b..91660c5 100644
--- a/src/main/java/com/sparrowwallet/sparrow/io/ColdcardMultisig.java
+++ b/src/main/java/com/sparrowwallet/sparrow/io/ColdcardMultisig.java
@@ -119,7 +119,7 @@ public class ColdcardMultisig implements WalletImport, KeystoreFileImport, Walle
@Override
public Wallet importWallet(InputStream inputStream, String password) throws ImportException {
Wallet wallet = new Wallet();
- wallet.setPolicyType(PolicyType.MULTI);
+ wallet.setPolicyType(PolicyType.MULTI_HD);
int threshold = 2;
ScriptType scriptType = ScriptType.P2SH;
@@ -167,7 +167,7 @@ public class ColdcardMultisig implements WalletImport, KeystoreFileImport, Walle
}
- Policy policy = Policy.getPolicy(PolicyType.MULTI, scriptType, wallet.getKeystores(), threshold);
+ Policy policy = Policy.getPolicy(PolicyType.MULTI_HD, scriptType, wallet.getKeystores(), threshold);
wallet.setDefaultPolicy(policy);
wallet.setScriptType(scriptType);
@@ -194,7 +194,7 @@ public class ColdcardMultisig implements WalletImport, KeystoreFileImport, Walle
throw new ExportException("Cannot export an incomplete wallet");
}
- if(!wallet.getPolicyType().equals(PolicyType.MULTI)) {
+ if(!wallet.getPolicyType().equals(PolicyType.MULTI_HD)) {
throw new ExportException(getName() + " import requires a multisig wallet");
}
diff --git a/src/main/java/com/sparrowwallet/sparrow/io/ColdcardSinglesig.java b/src/main/java/com/sparrowwallet/sparrow/io/ColdcardSinglesig.java
index 0c95d33..df80e8c 100644
--- a/src/main/java/com/sparrowwallet/sparrow/io/ColdcardSinglesig.java
+++ b/src/main/java/com/sparrowwallet/sparrow/io/ColdcardSinglesig.java
@@ -104,10 +104,10 @@ public class ColdcardSinglesig implements KeystoreFileImport, WalletImport {
Keystore keystore = getKeystore(ScriptType.P2WPKH, inputStream, "");
Wallet wallet = new Wallet();
- wallet.setPolicyType(PolicyType.SINGLE);
+ wallet.setPolicyType(PolicyType.SINGLE_HD);
wallet.setScriptType(ScriptType.P2WPKH);
wallet.getKeystores().add(keystore);
- wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, wallet.getKeystores(), null));
+ wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, wallet.getKeystores(), null));
try {
wallet.checkWallet();
diff --git a/src/main/java/com/sparrowwallet/sparrow/io/Electrum.java b/src/main/java/com/sparrowwallet/sparrow/io/Electrum.java
index a8d995d..4e78ad7 100644
--- a/src/main/java/com/sparrowwallet/sparrow/io/Electrum.java
+++ b/src/main/java/com/sparrowwallet/sparrow/io/Electrum.java
@@ -43,7 +43,7 @@ public class Electrum implements KeystoreFileImport, WalletImport, WalletExport
public Keystore getKeystore(ScriptType scriptType, InputStream inputStream, String password) throws ImportException {
Wallet wallet = importWallet(inputStream, password);
- if(!wallet.getPolicyType().equals(PolicyType.SINGLE) || wallet.getKeystores().size() != 1) {
+ if(!wallet.getPolicyType().equals(PolicyType.SINGLE_HD) || wallet.getKeystores().size() != 1) {
throw new ImportException("Multisig wallet detected - import it using File > Import Wallet");
}
@@ -203,13 +203,13 @@ public class Electrum implements KeystoreFileImport, WalletImport, WalletExport
wallet.setScriptType(scriptType);
if(ew.wallet_type.equals("standard")) {
- wallet.setPolicyType(PolicyType.SINGLE);
- wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, scriptType, wallet.getKeystores(), 1));
+ wallet.setPolicyType(PolicyType.SINGLE_HD);
+ wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, scriptType, wallet.getKeystores(), 1));
} else if(ew.wallet_type.contains("of")) {
- wallet.setPolicyType(PolicyType.MULTI);
+ wallet.setPolicyType(PolicyType.MULTI_HD);
String[] mOfn = ew.wallet_type.split("of");
int threshold = Integer.parseInt(mOfn[0]);
- wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.MULTI, scriptType, wallet.getKeystores(), threshold));
+ wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.MULTI_HD, scriptType, wallet.getKeystores(), threshold));
} else {
throw new ImportException("Unknown Electrum wallet type of " + ew.wallet_type);
}
@@ -308,9 +308,9 @@ public class Electrum implements KeystoreFileImport, WalletImport, WalletExport
public void exportWallet(Wallet wallet, OutputStream outputStream, String password) throws ExportException {
try {
ElectrumJsonWallet ew = new ElectrumJsonWallet();
- if(wallet.getPolicyType().equals(PolicyType.SINGLE)) {
+ if(wallet.getPolicyType().equals(PolicyType.SINGLE_HD)) {
ew.wallet_type = "standard";
- } else if(wallet.getPolicyType().equals(PolicyType.MULTI)) {
+ } else if(wallet.getPolicyType().equals(PolicyType.MULTI_HD)) {
ew.wallet_type = wallet.getDefaultPolicy().getNumSignaturesRequired() + "of" + wallet.getKeystores().size();
} else {
throw new ExportException("Could not export a wallet with a " + wallet.getPolicyType() + " policy");
@@ -367,9 +367,9 @@ public class Electrum implements KeystoreFileImport, WalletImport, WalletExport
throw new ExportException("Cannot export a keystore of source " + keystore.getSource());
}
- if(wallet.getPolicyType().equals(PolicyType.SINGLE)) {
+ if(wallet.getPolicyType().equals(PolicyType.SINGLE_HD)) {
ew.keystores.put("keystore", ek);
- } else if(wallet.getPolicyType().equals(PolicyType.MULTI)) {
+ } else if(wallet.getPolicyType().equals(PolicyType.MULTI_HD)) {
ew.keystores.put("x" + index + "/", ek);
}
diff --git a/src/main/java/com/sparrowwallet/sparrow/io/ElectrumPersonalServer.java b/src/main/java/com/sparrowwallet/sparrow/io/ElectrumPersonalServer.java
index ddcb4cf..23f9554 100644
--- a/src/main/java/com/sparrowwallet/sparrow/io/ElectrumPersonalServer.java
+++ b/src/main/java/com/sparrowwallet/sparrow/io/ElectrumPersonalServer.java
@@ -30,6 +30,10 @@ public class ElectrumPersonalServer implements WalletExport {
@Override
public void exportWallet(Wallet wallet, OutputStream outputStream, String password) throws ExportException {
+ if(wallet.getPolicyType() == PolicyType.SINGLE_SILENT_PAYMENTS) {
+ throw new ExportException(getName() + " does not support silent payments wallets.");
+ }
+
if(wallet.getScriptType() == ScriptType.P2TR) {
throw new ExportException(getName() + " does not support Taproot wallets.");
}
diff --git a/src/main/java/com/sparrowwallet/sparrow/io/KeystoneSinglesig.java b/src/main/java/com/sparrowwallet/sparrow/io/KeystoneSinglesig.java
index 08c6186..b8d518c 100644
--- a/src/main/java/com/sparrowwallet/sparrow/io/KeystoneSinglesig.java
+++ b/src/main/java/com/sparrowwallet/sparrow/io/KeystoneSinglesig.java
@@ -1,6 +1,5 @@
package com.sparrowwallet.sparrow.io;
-import com.google.gson.Gson;
import com.sparrowwallet.drongo.ExtendedKey;
import com.sparrowwallet.drongo.KeyDerivation;
import com.sparrowwallet.drongo.OutputDescriptor;
@@ -79,10 +78,10 @@ public class KeystoneSinglesig implements KeystoreFileImport, WalletImport {
Keystore keystore = getKeystore(ScriptType.P2WPKH, inputStream, "");
Wallet wallet = new Wallet();
- wallet.setPolicyType(PolicyType.SINGLE);
+ wallet.setPolicyType(PolicyType.SINGLE_HD);
wallet.setScriptType(ScriptType.P2WPKH);
wallet.getKeystores().add(keystore);
- wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, wallet.getKeystores(), null));
+ wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, wallet.getKeystores(), null));
try {
wallet.checkWallet();
diff --git a/src/main/java/com/sparrowwallet/sparrow/io/Storage.java b/src/main/java/com/sparrowwallet/sparrow/io/Storage.java
index b17b073..dface64 100644
--- a/src/main/java/com/sparrowwallet/sparrow/io/Storage.java
+++ b/src/main/java/com/sparrowwallet/sparrow/io/Storage.java
@@ -2,6 +2,7 @@ package com.sparrowwallet.sparrow.io;
import com.sparrowwallet.drongo.*;
import com.sparrowwallet.drongo.crypto.*;
+import com.sparrowwallet.drongo.policy.PolicyType;
import com.sparrowwallet.drongo.wallet.Keystore;
import com.sparrowwallet.drongo.wallet.MnemonicException;
import com.sparrowwallet.drongo.wallet.StandardAccount;
@@ -187,6 +188,7 @@ public class Storage {
keystore.setExtendedPublicKey(derivedKeystore.getExtendedPublicKey());
keystore.getSeed().setPassphrase(copyKeystore.getSeed().getPassphrase());
keystore.setBip47ExtendedPrivateKey(derivedKeystore.getBip47ExtendedPrivateKey());
+ keystore.setSilentPaymentScanAddress(wallet.getPolicyType() == PolicyType.SINGLE_SILENT_PAYMENTS ? derivedKeystore.getSilentPaymentScanAddress() : null);
copyKeystore.getSeed().clear();
} else if(keystore.hasMasterPrivateExtendedKey()) {
Keystore copyKeystore = copy.getKeystores().get(i);
@@ -194,6 +196,7 @@ public class Storage {
keystore.setKeyDerivation(derivedKeystore.getKeyDerivation());
keystore.setExtendedPublicKey(derivedKeystore.getExtendedPublicKey());
keystore.setBip47ExtendedPrivateKey(derivedKeystore.getBip47ExtendedPrivateKey());
+ keystore.setSilentPaymentScanAddress(wallet.getPolicyType() == PolicyType.SINGLE_SILENT_PAYMENTS ? derivedKeystore.getSilentPaymentScanAddress() : null);
copyKeystore.getMasterPrivateKey().clear();
}
}
diff --git a/src/main/java/com/sparrowwallet/sparrow/io/ckcard/CkCardApi.java b/src/main/java/com/sparrowwallet/sparrow/io/ckcard/CkCardApi.java
index 6455bf4..909c244 100644
--- a/src/main/java/com/sparrowwallet/sparrow/io/ckcard/CkCardApi.java
+++ b/src/main/java/com/sparrowwallet/sparrow/io/ckcard/CkCardApi.java
@@ -6,6 +6,7 @@ import com.sparrowwallet.drongo.Utils;
import com.sparrowwallet.drongo.address.Address;
import com.sparrowwallet.drongo.crypto.ChildNumber;
import com.sparrowwallet.drongo.crypto.ECKey;
+import com.sparrowwallet.drongo.policy.PolicyType;
import com.sparrowwallet.drongo.protocol.*;
import com.sparrowwallet.drongo.psbt.PSBT;
import com.sparrowwallet.drongo.psbt.PSBTInput;
@@ -300,7 +301,7 @@ public class CkCardApi extends CardApi {
}
CardRead cardRead = cardProtocol.read(null, currentSlot);
- Address address = getDefaultScriptType().getAddress(cardRead.getPubKey());
+ Address address = getDefaultScriptType().getAddress(PolicyType.SINGLE_HD, cardRead.getPubKey());
String left = addr.substring(0, addr.indexOf('_'));
String right = addr.substring(addr.lastIndexOf('_') + 1);
diff --git a/src/main/java/com/sparrowwallet/sparrow/net/LnurlAuth.java b/src/main/java/com/sparrowwallet/sparrow/net/LnurlAuth.java
index b15be3a..3311e0b 100644
--- a/src/main/java/com/sparrowwallet/sparrow/net/LnurlAuth.java
+++ b/src/main/java/com/sparrowwallet/sparrow/net/LnurlAuth.java
@@ -151,8 +151,8 @@ public class LnurlAuth {
}
private ECKey deriveLinkingKey(Wallet wallet) {
- if(wallet.getPolicyType() != PolicyType.SINGLE) {
- throw new IllegalArgumentException("Only singlesig wallets can authenticate.");
+ if(wallet.getPolicyType() != PolicyType.SINGLE_HD) {
+ throw new IllegalArgumentException("Only singlesig HD wallets can authenticate.");
}
if(wallet.isEncrypted()) {
diff --git a/src/main/java/com/sparrowwallet/sparrow/net/VersionCheckService.java b/src/main/java/com/sparrowwallet/sparrow/net/VersionCheckService.java
index 55ee45b..c389615 100644
--- a/src/main/java/com/sparrowwallet/sparrow/net/VersionCheckService.java
+++ b/src/main/java/com/sparrowwallet/sparrow/net/VersionCheckService.java
@@ -4,6 +4,7 @@ import com.sparrowwallet.drongo.Version;
import com.sparrowwallet.drongo.address.Address;
import com.sparrowwallet.drongo.address.InvalidAddressException;
import com.sparrowwallet.drongo.crypto.ECKey;
+import com.sparrowwallet.drongo.policy.PolicyType;
import com.sparrowwallet.drongo.protocol.ScriptType;
import com.sparrowwallet.sparrow.AppServices;
import com.sparrowwallet.sparrow.SparrowWallet;
@@ -66,7 +67,7 @@ public class VersionCheckService extends ScheduledService<VersionUpdatedEvent> {
String signature = versionCheck.signatures.get(addressString);
ECKey signedMessageKey = ECKey.signedMessageToKey(versionCheck.version, signature, false);
Address providedAddress = Address.fromString(addressString);
- Address signedMessageAddress = ScriptType.P2PKH.getAddress(signedMessageKey);
+ Address signedMessageAddress = ScriptType.P2PKH.getAddress(PolicyType.SINGLE_HD, signedMessageKey);
if(providedAddress.equals(signedMessageAddress)) {
return true;
diff --git a/src/main/java/com/sparrowwallet/sparrow/terminal/wallet/Bip39Dialog.java b/src/main/java/com/sparrowwallet/sparrow/terminal/wallet/Bip39Dialog.java
index 17e6945..1b5b9b1 100644
--- a/src/main/java/com/sparrowwallet/sparrow/terminal/wallet/Bip39Dialog.java
+++ b/src/main/java/com/sparrowwallet/sparrow/terminal/wallet/Bip39Dialog.java
@@ -68,7 +68,7 @@ public class Bip39Dialog extends NewWalletDialog {
buttonPanel.setLayoutData(GridLayout.createLayoutData(GridLayout.Alignment.END, GridLayout.Alignment.CENTER,false,false)).addTo(mainPanel);
setComponent(mainPanel);
- ScriptType.getAddressableScriptTypes(PolicyType.SINGLE).stream().map(DisplayScriptType::new).forEach(scriptType::addItem);
+ ScriptType.getAddressableScriptTypes(PolicyType.SINGLE_HD).stream().map(DisplayScriptType::new).forEach(scriptType::addItem);
scriptType.setSelectedItem(new DisplayScriptType(ScriptType.P2WPKH));
seedWords.setTextChangeListener((newText, changedByUserInteraction) -> {
@@ -150,11 +150,11 @@ public class Bip39Dialog extends NewWalletDialog {
@Override
protected List<Wallet> getWallets() throws ImportException {
Wallet wallet = new Wallet(walletName);
- wallet.setPolicyType(PolicyType.SINGLE);
+ wallet.setPolicyType(PolicyType.SINGLE_HD);
wallet.setScriptType(scriptType.getSelectedItem().scriptType);
Keystore keystore = importer.getKeystore(wallet.getScriptType().getDefaultDerivation(), getWords(), passphrase.getText());
wallet.getKeystores().add(keystore);
- wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, wallet.getScriptType(), wallet.getKeystores(), 1));
+ wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, wallet.getScriptType(), wallet.getKeystores(), 1));
return List.of(wallet);
}
diff --git a/src/main/java/com/sparrowwallet/sparrow/terminal/wallet/SettingsDialog.java b/src/main/java/com/sparrowwallet/sparrow/terminal/wallet/SettingsDialog.java
index b814200..fb7f1ca 100644
--- a/src/main/java/com/sparrowwallet/sparrow/terminal/wallet/SettingsDialog.java
+++ b/src/main/java/com/sparrowwallet/sparrow/terminal/wallet/SettingsDialog.java
@@ -75,7 +75,7 @@ public class SettingsDialog extends WalletDialog {
Panel leftButtonPanel = new Panel();
leftButtonPanel.setLayoutManager(new GridLayout(2).setHorizontalSpacing(1));
leftButtonPanel.addComponent(new Button("Add Account", this::showAddAccount));
- if(getWalletForm().getWallet().getPolicyType() == PolicyType.SINGLE) {
+ if(getWalletForm().getWallet().getPolicyType() == PolicyType.SINGLE || getWalletForm().getWallet().getPolicyType() == PolicyType.SINGLE_SILENT_PAYMENTS) {
leftButtonPanel.addComponent(new Button("Show Seed", this::showSeed));
} else {
leftButtonPanel.addComponent(new EmptySpace(TerminalSize.ZERO));
diff --git a/src/main/java/com/sparrowwallet/sparrow/terminal/wallet/WatchOnlyDialog.java b/src/main/java/com/sparrowwallet/sparrow/terminal/wallet/WatchOnlyDialog.java
index b698027..bd974d4 100644
--- a/src/main/java/com/sparrowwallet/sparrow/terminal/wallet/WatchOnlyDialog.java
+++ b/src/main/java/com/sparrowwallet/sparrow/terminal/wallet/WatchOnlyDialog.java
@@ -113,12 +113,12 @@ public class WatchOnlyDialog extends NewWalletDialog {
Set<ScriptType> scriptTypes = new LinkedHashSet<>();
scriptTypes.add(ScriptType.P2WPKH);
scriptTypes.add(header.getDefaultScriptType());
- scriptTypes.addAll(ScriptType.getAddressableScriptTypes(PolicyType.SINGLE));
+ scriptTypes.addAll(ScriptType.getAddressableScriptTypes(PolicyType.SINGLE_HD));
List<Wallet> wallets = new ArrayList<>();
for(ScriptType scriptType : scriptTypes) {
Wallet wallet = new Wallet(walletName);
- wallet.setPolicyType(PolicyType.SINGLE);
+ wallet.setPolicyType(PolicyType.SINGLE_HD);
wallet.setScriptType(scriptType);
Keystore keystore = new Keystore();
diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java b/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java
index 8e83e07..e695d05 100644
--- a/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java
+++ b/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java
@@ -849,7 +849,7 @@ public class HeadersController extends TransactionFormController implements Init
}
if(headersForm.getWalletTransaction() != null && headersForm.getWalletTransaction().getWallet() != null
- && headersForm.getWalletTransaction().getWallet().getPolicyType() == PolicyType.MULTI
+ && headersForm.getWalletTransaction().getWallet().getPolicyType() == PolicyType.MULTI_HD
&& headersForm.getWalletTransaction().getWallet().getDefaultPolicy().getNumSignaturesRequired() < headersForm.getWalletTransaction().getWallet().getKeystores().size()) {
signedByField.setVisible(true);
Wallet wallet = headersForm.getWalletTransaction().getWallet();
diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/PaymentController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/PaymentController.java
index 329425b..11cd858 100644
--- a/src/main/java/com/sparrowwallet/sparrow/wallet/PaymentController.java
+++ b/src/main/java/com/sparrowwallet/sparrow/wallet/PaymentController.java
@@ -61,7 +61,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URL;
-import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.TimeoutException;
@@ -571,7 +570,7 @@ public class PaymentController extends WalletFormController implements Initializ
sendNode = recipientBip47Wallet.getFreshNode(KeyPurpose.SEND, sendNode);
}
ECKey pubKey = sendNode.getPubKey();
- return recipientBip47Wallet.getScriptType().getAddress(pubKey);
+ return recipientBip47Wallet.getScriptType().getAddress(recipientBip47Wallet.getPolicyType(), pubKey);
}
} catch(InvalidPaymentCodeException e) {
log.error("Error creating payment code from PayNym", e);
diff --git a/src/test/java/com/sparrowwallet/sparrow/io/CaravanMultisigTest.java b/src/test/java/com/sparrowwallet/sparrow/io/CaravanMultisigTest.java
index 0ab2281..294c2c5 100644
--- a/src/test/java/com/sparrowwallet/sparrow/io/CaravanMultisigTest.java
+++ b/src/test/java/com/sparrowwallet/sparrow/io/CaravanMultisigTest.java
@@ -19,7 +19,7 @@ public class CaravanMultisigTest extends IoTest {
CaravanMultisig ccMultisig = new CaravanMultisig();
Wallet wallet = ccMultisig.importWallet(getInputStream("caravan-multisig-export-1.json"), null);
Assertions.assertEquals("Test Wallet", wallet.getName());
- Assertions.assertEquals(PolicyType.MULTI, wallet.getPolicyType());
+ Assertions.assertEquals(PolicyType.MULTI_HD, wallet.getPolicyType());
Assertions.assertEquals(ScriptType.P2WSH, wallet.getScriptType());
Assertions.assertEquals(2, wallet.getDefaultPolicy().getNumSignaturesRequired());
Assertions.assertEquals("wsh(sortedmulti(2,mercury,venus,earth))", wallet.getDefaultPolicy().getMiniscript().getScript().toLowerCase(Locale.ROOT));
diff --git a/src/test/java/com/sparrowwallet/sparrow/io/ColdcardMultisigTest.java b/src/test/java/com/sparrowwallet/sparrow/io/ColdcardMultisigTest.java
index 8978870..487facf 100644
--- a/src/test/java/com/sparrowwallet/sparrow/io/ColdcardMultisigTest.java
+++ b/src/test/java/com/sparrowwallet/sparrow/io/ColdcardMultisigTest.java
@@ -62,7 +62,7 @@ public class ColdcardMultisigTest extends IoTest {
ColdcardMultisig ccMultisig = new ColdcardMultisig();
Wallet wallet = ccMultisig.importWallet(getInputStream("cc-multisig-export-1.txt"), null);
Assertions.assertEquals("CC-2-of-4", wallet.getName());
- Assertions.assertEquals(PolicyType.MULTI, wallet.getPolicyType());
+ Assertions.assertEquals(PolicyType.MULTI_HD, wallet.getPolicyType());
Assertions.assertEquals(ScriptType.P2WSH, wallet.getScriptType());
Assertions.assertEquals(2, wallet.getDefaultPolicy().getNumSignaturesRequired());
Assertions.assertEquals("wsh(sortedmulti(2,coldcard1,coldcard2,coldcard3,coldcard4))", wallet.getDefaultPolicy().getMiniscript().getScript().toLowerCase(Locale.ROOT));
@@ -75,7 +75,7 @@ public class ColdcardMultisigTest extends IoTest {
ColdcardMultisig ccMultisig = new ColdcardMultisig();
Wallet wallet = ccMultisig.importWallet(getInputStream("cc-multisig-export-2.txt"), null);
Assertions.assertEquals("CC-2-of-4", wallet.getName());
- Assertions.assertEquals(PolicyType.MULTI, wallet.getPolicyType());
+ Assertions.assertEquals(PolicyType.MULTI_HD, wallet.getPolicyType());
Assertions.assertEquals(ScriptType.P2SH_P2WSH, wallet.getScriptType());
Assertions.assertEquals(2, wallet.getDefaultPolicy().getNumSignaturesRequired());
Assertions.assertEquals("sh(wsh(sortedmulti(2,coldcard1,coldcard2,coldcard3,coldcard4)))", wallet.getDefaultPolicy().getMiniscript().getScript().toLowerCase(Locale.ROOT));
@@ -87,7 +87,7 @@ public class ColdcardMultisigTest extends IoTest {
ColdcardMultisig ccMultisig = new ColdcardMultisig();
Wallet wallet = ccMultisig.importWallet(getInputStream("cc-multisig-export-multideriv.txt"), null);
Assertions.assertEquals("el-CC-3-of-3-sb-2", wallet.getName());
- Assertions.assertEquals(PolicyType.MULTI, wallet.getPolicyType());
+ Assertions.assertEquals(PolicyType.MULTI_HD, wallet.getPolicyType());
Assertions.assertEquals(ScriptType.P2WSH, wallet.getScriptType());
Assertions.assertEquals(3, wallet.getDefaultPolicy().getNumSignaturesRequired());
Assertions.assertEquals("wsh(sortedmulti(3,coldcard1,coldcard2,coldcard3))", wallet.getDefaultPolicy().getMiniscript().getScript().toLowerCase(Locale.ROOT));
diff --git a/src/test/java/com/sparrowwallet/sparrow/io/ElectrumTest.java b/src/test/java/com/sparrowwallet/sparrow/io/ElectrumTest.java
index bf05c30..9927f9b 100644
--- a/src/test/java/com/sparrowwallet/sparrow/io/ElectrumTest.java
+++ b/src/test/java/com/sparrowwallet/sparrow/io/ElectrumTest.java
@@ -22,7 +22,7 @@ public class ElectrumTest extends IoTest {
Electrum electrum = new Electrum();
Wallet wallet = electrum.importWallet(getInputStream("electrum-singlesig-wallet.json"), null);
- Assertions.assertEquals(PolicyType.SINGLE, wallet.getPolicyType());
+ Assertions.assertEquals(PolicyType.SINGLE_HD, wallet.getPolicyType());
Assertions.assertEquals(ScriptType.P2SH_P2WPKH, wallet.getScriptType());
Assertions.assertEquals(1, wallet.getDefaultPolicy().getNumSignaturesRequired());
Assertions.assertEquals("sh(wpkh(trezortest))", wallet.getDefaultPolicy().getMiniscript().getScript().toLowerCase(Locale.ROOT));
@@ -42,7 +42,7 @@ public class ElectrumTest extends IoTest {
wallet = electrum.importWallet(new ByteArrayInputStream(baos.toByteArray()), null);
Assertions.assertTrue(wallet.isValid());
- Assertions.assertEquals(PolicyType.SINGLE, wallet.getPolicyType());
+ Assertions.assertEquals(PolicyType.SINGLE_HD, wallet.getPolicyType());
Assertions.assertEquals(ScriptType.P2SH_P2WPKH, wallet.getScriptType());
Assertions.assertEquals(1, wallet.getDefaultPolicy().getNumSignaturesRequired());
Assertions.assertEquals("sh(wpkh(trezortest))", wallet.getDefaultPolicy().getMiniscript().getScript().toLowerCase(Locale.ROOT));
@@ -57,7 +57,7 @@ public class ElectrumTest extends IoTest {
Electrum electrum = new Electrum();
Wallet wallet = electrum.importWallet(getInputStream("electrum-multisig-wallet.json"), null);
- Assertions.assertEquals(PolicyType.MULTI, wallet.getPolicyType());
+ Assertions.assertEquals(PolicyType.MULTI_HD, wallet.getPolicyType());
Assertions.assertEquals(ScriptType.P2SH_P2WSH, wallet.getScriptType());
Assertions.assertEquals(2, wallet.getDefaultPolicy().getNumSignaturesRequired());
Assertions.assertEquals("sh(wsh(sortedmulti(2,coldcard6ba6cfd,coldcard747b698,coldcard7bb026b,coldcard0f05694)))", wallet.getDefaultPolicy().getMiniscript().getScript().toLowerCase(Locale.ROOT));
@@ -80,7 +80,7 @@ public class ElectrumTest extends IoTest {
wallet = electrum.importWallet(new ByteArrayInputStream(baos.toByteArray()), null);
Assertions.assertTrue(wallet.isValid());
- Assertions.assertEquals(PolicyType.MULTI, wallet.getPolicyType());
+ Assertions.assertEquals(PolicyType.MULTI_HD, wallet.getPolicyType());
Assertions.assertEquals(ScriptType.P2SH_P2WSH, wallet.getScriptType());
Assertions.assertEquals(2, wallet.getDefaultPolicy().getNumSignaturesRequired());
Assertions.assertEquals("sh(wsh(sortedmulti(2,coldcard6ba6cfd,coldcard747b698,coldcard7bb026b,coldcard0f05694)))", wallet.getDefaultPolicy().getMiniscript().getScript().toLowerCase(Locale.ROOT));
@@ -98,7 +98,7 @@ public class ElectrumTest extends IoTest {
Wallet wallet = electrum.importWallet(new ByteArrayInputStream(walletBytes), "pass");
Assertions.assertTrue(wallet.isValid());
- Assertions.assertEquals(PolicyType.SINGLE, wallet.getPolicyType());
+ Assertions.assertEquals(PolicyType.SINGLE_HD, wallet.getPolicyType());
Assertions.assertEquals(ScriptType.P2WPKH, wallet.getScriptType());
Assertions.assertEquals(1, wallet.getDefaultPolicy().getNumSignaturesRequired());
Assertions.assertEquals("wpkh(electrum)", wallet.getDefaultPolicy().getMiniscript().getScript().toLowerCase(Locale.ROOT));
@@ -118,7 +118,7 @@ public class ElectrumTest extends IoTest {
wallet = electrum.importWallet(new ByteArrayInputStream(baos.toByteArray()), null);
Assertions.assertTrue(wallet.isValid());
- Assertions.assertEquals(PolicyType.SINGLE, wallet.getPolicyType());
+ Assertions.assertEquals(PolicyType.SINGLE_HD, wallet.getPolicyType());
Assertions.assertEquals(ScriptType.P2WPKH, wallet.getScriptType());
Assertions.assertEquals(1, wallet.getDefaultPolicy().getNumSignaturesRequired());
Assertions.assertEquals("wpkh(electrum)", wallet.getDefaultPolicy().getMiniscript().getScript().toLowerCase(Locale.ROOT));
diff --git a/src/test/java/com/sparrowwallet/sparrow/io/SpecterDesktopTest.java b/src/test/java/com/sparrowwallet/sparrow/io/SpecterDesktopTest.java
index 3c60a16..5a14b62 100644
--- a/src/test/java/com/sparrowwallet/sparrow/io/SpecterDesktopTest.java
+++ b/src/test/java/com/sparrowwallet/sparrow/io/SpecterDesktopTest.java
@@ -14,7 +14,7 @@ public class SpecterDesktopTest extends IoTest {
SpecterDesktop specterDesktop = new SpecterDesktop();
Wallet wallet = specterDesktop.importWallet(getInputStream("specter-wallet.json"), null);
- Assertions.assertEquals(PolicyType.SINGLE, wallet.getPolicyType());
+ Assertions.assertEquals(PolicyType.SINGLE_HD, wallet.getPolicyType());
Assertions.assertEquals(ScriptType.P2SH_P2WPKH, wallet.getScriptType());
Assertions.assertEquals(1, wallet.getDefaultPolicy().getNumSignaturesRequired());
Assertions.assertEquals("sh(wpkh(keystore1))", wallet.getDefaultPolicy().getMiniscript().getScript().toLowerCase(Locale.ROOT));
@@ -29,7 +29,7 @@ public class SpecterDesktopTest extends IoTest {
SpecterDesktop specterDesktop = new SpecterDesktop();
Wallet wallet = specterDesktop.importWallet(getInputStream("specter-multisig-wallet.json"), null);
- Assertions.assertEquals(PolicyType.MULTI, wallet.getPolicyType());
+ Assertions.assertEquals(PolicyType.MULTI_HD, wallet.getPolicyType());
Assertions.assertEquals(ScriptType.P2WSH, wallet.getScriptType());
Assertions.assertEquals(3, wallet.getDefaultPolicy().getNumSignaturesRequired());
Assertions.assertEquals("wsh(sortedmulti(3,keystore1,keystore2,keystore3,keystore4))", wallet.getDefaultPolicy().getMiniscript().getScript().toLowerCase(Locale.ROOT));
diff --git a/src/test/java/com/sparrowwallet/sparrow/io/StorageTest.java b/src/test/java/com/sparrowwallet/sparrow/io/StorageTest.java
index 4b6ef52..1aa89cb 100644
--- a/src/test/java/com/sparrowwallet/sparrow/io/StorageTest.java
+++ b/src/test/java/com/sparrowwallet/sparrow/io/StorageTest.java
@@ -45,7 +45,7 @@ public class StorageTest extends IoTest {
Assertions.assertTrue(wallet.isValid());
Assertions.assertEquals("testd2", wallet.getName());
- Assertions.assertEquals(PolicyType.SINGLE, wallet.getPolicyType());
+ Assertions.assertEquals(PolicyType.SINGLE_HD, wallet.getPolicyType());
Assertions.assertEquals(ScriptType.P2WPKH, wallet.getScriptType());
Assertions.assertEquals(1, wallet.getDefaultPolicy().getNumSignaturesRequired());
Assertions.assertEquals("pkh(60bcd3a7)", wallet.getDefaultPolicy().getMiniscript().getScript());
Why this scored 24/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.