hide the gap limit and request a birth date for a silent payments wallet in the terminal
What changed, and why it matters
This commit tweaks the terminal (command-line) version of Sparrow Wallet. For a new type of wallet called a 'silent payments' wallet, it hides the 'gap limit' setting (which doesn't apply) and asks the user for the wallet's creation date when importing a watch-only silent-payments wallet. This is a user-interface improvement, not a security fix.
No security action required; treat as a normal UI/UX improvement. Reviewers may optionally verify that the birth date prompt is shown consistently across GUI and terminal flows.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch modifies two terminal UI dialogs. AdvancedDialog now checks if the wallet policy type is SINGLE_SP (single-signature silent payments) and, if so, skips adding the gap limit input because silent payments wallets do not derive lookahead addresses. WatchOnlyDialog now prompts the user to enter a birth date when importing a silent payments output descriptor that lacks both birthDate and birthHeight. The birth date is used to bound blockchain scanning. There is no change to cryptographic logic, validation, or access control.
Changed components
src/main/java/com/sparrowwallet/sparrow/terminal/wallet/AdvancedDialog.javasrc/main/java/com/sparrowwallet/sparrow/terminal/wallet/WatchOnlyDialog.javaInspect captured patch +52 / −15
### src/main/java/com/sparrowwallet/sparrow/terminal/wallet/AdvancedDialog.java
@@ -2,6 +2,7 @@
import com.googlecode.lanterna.TerminalSize;
import com.googlecode.lanterna.gui2.*;
+import com.sparrowwallet.drongo.policy.PolicyType;
import com.sparrowwallet.drongo.wallet.Wallet;
import com.sparrowwallet.sparrow.io.Storage;
import com.sparrowwallet.sparrow.wallet.WalletForm;
@@ -39,9 +40,14 @@ public AdvancedDialog(WalletForm walletForm) {
birthDate = new TextBox().setValidationPattern(Pattern.compile("[0-9\\-/]*"));
mainPanel.addComponent(birthDate);
- mainPanel.addComponent(new Label("Gap limit"));
- gapLimit = new TextBox().setValidationPattern(Pattern.compile("[0-9]*"));
- mainPanel.addComponent(gapLimit);
+ //A silent payments wallet derives no addresses to look ahead over, and getGapLimit() returns zero whatever is stored
+ if(wallet.getPolicyType() == PolicyType.SINGLE_SP) {
+ gapLimit = null;
+ } else {
+ mainPanel.addComponent(new Label("Gap limit"));
+ gapLimit = new TextBox().setValidationPattern(Pattern.compile("[0-9]*"));
+ mainPanel.addComponent(gapLimit);
+ }
Panel buttonPanel = new Panel();
buttonPanel.setLayoutManager(new GridLayout(2).setHorizontalSpacing(1));
@@ -60,7 +66,9 @@ public AdvancedDialog(WalletForm walletForm) {
birthDate.setText(DATE_FORMAT.format(wallet.getBirthDate()));
}
- gapLimit.setText(Integer.toString(wallet.getGapLimit()));
+ if(gapLimit != null) {
+ gapLimit.setText(Integer.toString(wallet.getGapLimit()));
+ }
birthDate.setTextChangeListener((newText, changedByUserInteraction) -> {
try {
@@ -73,19 +81,21 @@ public AdvancedDialog(WalletForm walletForm) {
}
});
- gapLimit.setTextChangeListener((newText, changedByUserInteraction) -> {
- try {
- int newValue = Integer.parseInt(newText);
- if(newValue < 0 || newValue > 1000000) {
+ if(gapLimit != null) {
+ gapLimit.setTextChangeListener((newText, changedByUserInteraction) -> {
+ try {
+ int newValue = Integer.parseInt(newText);
+ if(newValue < 0 || newValue > 1000000) {
+ return;
+ }
+
+ wallet.setGapLimit(newValue);
+ apply.setEnabled(true);
+ } catch(NumberFormatException e) {
return;
}
-
- wallet.setGapLimit(newValue);
- apply.setEnabled(true);
- } catch(NumberFormatException e) {
- return;
- }
- });
+ });
+ }
}
private void onChangePassword() {
### src/main/java/com/sparrowwallet/sparrow/terminal/wallet/WatchOnlyDialog.java
@@ -3,6 +3,7 @@
import com.googlecode.lanterna.TerminalPosition;
import com.googlecode.lanterna.TerminalSize;
import com.googlecode.lanterna.gui2.*;
+import com.googlecode.lanterna.gui2.dialogs.TextInputDialogBuilder;
import com.sparrowwallet.drongo.ExtendedKey;
import com.sparrowwallet.drongo.KeyDerivation;
import com.sparrowwallet.drongo.OutputDescriptor;
@@ -18,11 +19,15 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
import java.util.*;
public class WatchOnlyDialog extends NewWalletDialog {
private static final Logger log = LoggerFactory.getLogger(WatchOnlyDialog.class);
+ private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
+
private final TextBox descriptor;
private final Button importWallet;
@@ -143,9 +148,31 @@ private List<Wallet> getWalletFromOutputDescriptor(String text) {
OutputDescriptor outputDescriptor = OutputDescriptor.getOutputDescriptor(text);
Wallet wallet = outputDescriptor.toWallet();
wallet.setName(walletName);
+ if(wallet.getPolicyType() == PolicyType.SINGLE_SP && wallet.getBirthDate() == null && wallet.getBirthHeight() == null) {
+ wallet.setBirthDate(requestBirthDate());
+ }
+
return List.of(wallet);
}
+ private Date requestBirthDate() {
+ TextInputDialogBuilder builder = new TextInputDialogBuilder().setTitle("Wallet Birth Date");
+ builder.setDescription("Silent payments are scanned for from this date onwards." + System.lineSeparator() + "Enter the date this wallet was created as " + DATE_FORMAT.toPattern() + ".");
+ builder.setInitialContent(DATE_FORMAT.format(new Date()));
+
+ String enteredDate = builder.build().showDialog(SparrowTerminal.get().getGui());
+ if(enteredDate == null || enteredDate.isBlank()) {
+ return null;
+ }
+
+ try {
+ return DATE_FORMAT.parse(enteredDate.trim());
+ } catch(ParseException e) {
+ log.warn("Could not parse the birth date entered for " + walletName);
+ return null;
+ }
+ }
+
private List<String> splitString(String stringToSplit, int maxLength) {
String text = stringToSplit.replaceAll("\\s+", "");
if(stringToSplit.endsWith("\n")) {Why this scored 18/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.