include the non-witness utxo in psbts for krux keystores, and in the qr display when the psbt has more than one input
What changed, and why it matters
This commit changes how Sparrow Wallet builds QR codes for partially-signed Bitcoin transactions (PSBTs). For certain hardware wallets (Krux), it now includes extra data (the full previous transaction, called 'non-witness utxo') in the QR code when the transaction has more than one input. This extra data is needed by some devices to verify inputs securely, but it also makes the QR code larger and slower to scan. The change appears to be a correctness/usability fix for hardware signing rather than a traditional software vulnerability.
Review the drongo subproject diff to confirm the includeNonWitnessUtxoForQR() implementation and ensure it only adds non-witness UTXOs when required. Test QR scanning with multi-input segwit transactions on Krux devices to verify compatibility and scanning reliability. No immediate emergency action is indicated.
Security signals we found
Hardware wallet signing correctness: missing non-witness UTXO data can cause some signers to reject or mis-handle multi-input segwit PSBTs
QR payload size increase: larger QR codes may be harder to scan reliably, potentially affecting usability
Subproject update (drongo) likely contains related serialization logic changes
No explicit security language in commit title or message
Evidence from the diff
The patch modifies HeadersController.showPSBT() so that includeNonWitnessUtxos is true not only for non-segwit wallets, but also when (1) the PSBT has more than one input and (2) any keystore’s wallet model requires non-witness UTXO for QR display (Krux). It also updates the drongo subproject, presumably to add the includeNonWitnessUtxoForQR() method and the corresponding PSBT serialization behavior for Krux keystores. The previous behavior omitted non-witness UTXOs for segwit wallets to reduce QR scanning time, but some hardware signers require this data for multi-input segwit PSBTs.
Changed components
src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.javadrongo subprojectPSBT QR export flowKrux keystore integrationInspect captured patch +4 / −3
### drongo
@@ -1 +1 @@
-Subproject commit 9a8c659b49b6cb3010855b74a37e66e076521490
+Subproject commit a19eb5d9d4322469e4e07cd19da3e182cbd56639
### src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java
@@ -1133,8 +1133,9 @@ public void showPSBT(ActionEvent event) {
boolean addBbqrOption = headersForm.getSigningWallet().getKeystores().stream().anyMatch(keystore -> keystore.getWalletModel().showBbqr());
QREncoding encoding = headersForm.getSigningWallet().getKeystores().stream().allMatch(keystore -> keystore.getWalletModel().selectBbqr()) ? QREncoding.BBQR : QREncoding.UR;
- //Don't include non witness utxo fields for segwit wallets when displaying the PSBT as a QR - it can add greatly to the time required for scanning
- boolean includeNonWitnessUtxos = !Arrays.asList(ScriptType.WITNESS_TYPES).contains(headersForm.getSigningWallet().getScriptType());
+ //Don't include non witness utxo fields for segwit wallets when displaying the PSBT as a QR unless required - it can add greatly to the time required for scanning
+ boolean includeNonWitnessUtxos = !Arrays.asList(ScriptType.WITNESS_TYPES).contains(headersForm.getSigningWallet().getScriptType())
+ || (headersForm.getPsbt().getPsbtInputs().size() > 1 && headersForm.getSigningWallet().getKeystores().stream().anyMatch(keystore -> keystore.getWalletModel().includeNonWitnessUtxoForQR()));
byte[] psbtBytes = headersForm.getPsbt().getForExport().serialize(true, includeNonWitnessUtxos);
CryptoPSBT cryptoPSBT = new CryptoPSBT(psbtBytes);Why this scored 34/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.