restrict to required sighash types when sending sp outputs
What changed, and why it matters
This commit tightens which Bitcoin signature hash (sighash) types users can pick when sending to a silent payment address. Previously the UI offered all normal signing options; now it forces the recommended/required sighash (ALL for non-taproot, DEFAULT for taproot) and labels it as required. The change is defensive: using the wrong sighash type with silent payments could break privacy or make the transaction invalid, so the wallet now prevents that choice.
No urgent action for users; ensure the change is included in the next release. Developers should verify that the required sighash matches the BIP-352 silent payment specification and that hardware/external signers cannot override this restriction through another code path.
Security signals we found
silent payment output triggers mandatory sighash restriction
UI dropdown reduced to single required sighash
label changed from Recommended to Required for silent payment outputs
prevents user/external signer from choosing incompatible sighash types
Evidence from the diff
In HeadersController.java the sighash selector logic is changed so that when any PSBT output has a silent payment address, the dropdown is restricted to a single required sighash (SigHash.ALL for legacy inputs, SigHash.DEFAULT for taproot inputs) and the label changes from ‘Recommended’ to ‘Required’. The prior behavior allowed any taproot or legacy signing type and simply defaulted to the recommended one. This is a UI/policy restriction, not a consensus or cryptographic fix, but it closes a path where a user or external signer might select an incompatible sighash for a silent payment output.
Changed components
Sparrow Wallet desktop UIHeadersController.javatransaction sighash selection dialogsilent payment (BIP-352) send flowInspect captured patch +7 / −4
diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java b/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java
index c771cd4..2c1460c 100644
--- a/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java
+++ b/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java
@@ -532,8 +532,10 @@ public class HeadersController extends TransactionFormController implements Init
noWalletsWarningLink.visibleProperty().bind(noWalletsWarning.visibleProperty());
boolean taprootInput = psbt.getPsbtInputs().stream().anyMatch(PSBTInput::isTaproot);
- SigHash psbtSigHash = psbt.getPsbtInputs().stream().map(PSBTInput::getSigHash).filter(Objects::nonNull).findFirst().orElse(taprootInput ? SigHash.DEFAULT : SigHash.ALL);
- sigHash.setItems(FXCollections.observableList(taprootInput ? SigHash.TAPROOT_SIGNING_TYPES : SigHash.LEGACY_SIGNING_TYPES));
+ boolean silentPaymentOutput = psbt.getPsbtOutputs().stream().anyMatch(o -> o.getSilentPaymentAddress() != null);
+ SigHash requiredSigHash = taprootInput ? SigHash.DEFAULT : SigHash.ALL;
+ SigHash psbtSigHash = silentPaymentOutput ? requiredSigHash : psbt.getPsbtInputs().stream().map(PSBTInput::getSigHash).filter(Objects::nonNull).findFirst().orElse(requiredSigHash);
+ sigHash.setItems(FXCollections.observableList(silentPaymentOutput ? List.of(requiredSigHash) : (taprootInput ? SigHash.TAPROOT_SIGNING_TYPES : SigHash.LEGACY_SIGNING_TYPES)));
sigHash.setValue(psbtSigHash);
sigHash.setConverter(new StringConverter<>() {
@Override
@@ -542,7 +544,8 @@ public class HeadersController extends TransactionFormController implements Init
return "";
}
- return sigHash.getName() + ((taprootInput && sigHash == SigHash.DEFAULT) || (!taprootInput && sigHash == SigHash.ALL) ? " (Recommended)" : "");
+ boolean recommended = (taprootInput && sigHash == SigHash.DEFAULT) || (!taprootInput && sigHash == SigHash.ALL);
+ return sigHash.getName() + (recommended ? (silentPaymentOutput ? " (Required)" : " (Recommended)") : "");
}
@Override
Why this scored 42/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.