mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-11-02 20:36:44 +00:00
extra logging, backup existing wallet first functionality
This commit is contained in:
parent
03abc59ed3
commit
ce60fe3dc6
7 changed files with 75 additions and 3 deletions
|
@ -430,6 +430,7 @@ public class AppController implements Initializable {
|
|||
showErrorDialog("Invalid QR Code", result.error);
|
||||
}
|
||||
if(result.exception != null) {
|
||||
log.error("Error opening webcam", result.exception);
|
||||
showErrorDialog("Error opening webcam", result.exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
@ -474,6 +475,7 @@ public class AppController implements Initializable {
|
|||
}
|
||||
}
|
||||
} catch(IOException e) {
|
||||
log.error("Error saving transaction", e);
|
||||
AppController.showErrorDialog("Error saving transaction", "Cannot write to " + file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
@ -610,6 +612,7 @@ public class AppController implements Initializable {
|
|||
if(exception instanceof InvalidPasswordException) {
|
||||
showErrorDialog("Invalid Password", "The wallet password was invalid.");
|
||||
} else {
|
||||
log.error("Error Opening Wallet", exception);
|
||||
showErrorDialog("Error Opening Wallet", exception.getMessage());
|
||||
}
|
||||
});
|
||||
|
|
|
@ -20,11 +20,13 @@ public class WalletPasswordDialog extends Dialog<SecureString> {
|
|||
private final PasswordRequirement requirement;
|
||||
private final CustomPasswordField password;
|
||||
private final CustomPasswordField passwordConfirm;
|
||||
private final CheckBox backupExisting;
|
||||
|
||||
public WalletPasswordDialog(PasswordRequirement requirement) {
|
||||
this.requirement = requirement;
|
||||
this.password = (CustomPasswordField)TextFields.createClearablePasswordField();
|
||||
this.passwordConfirm = (CustomPasswordField)TextFields.createClearablePasswordField();
|
||||
this.backupExisting = new CheckBox("Backup existing wallet first");
|
||||
|
||||
final DialogPane dialogPane = getDialogPane();
|
||||
setTitle("Wallet Password");
|
||||
|
@ -32,7 +34,7 @@ public class WalletPasswordDialog extends Dialog<SecureString> {
|
|||
dialogPane.getStylesheets().add(AppController.class.getResource("general.css").toExternalForm());
|
||||
dialogPane.getButtonTypes().addAll(ButtonType.CANCEL);
|
||||
dialogPane.setPrefWidth(380);
|
||||
dialogPane.setPrefHeight(250);
|
||||
dialogPane.setPrefHeight(260);
|
||||
|
||||
Glyph lock = new Glyph("FontAwesome", FontAwesome.Glyph.LOCK);
|
||||
lock.setFontSize(50);
|
||||
|
@ -43,6 +45,11 @@ public class WalletPasswordDialog extends Dialog<SecureString> {
|
|||
content.getChildren().add(password);
|
||||
content.getChildren().add(passwordConfirm);
|
||||
|
||||
if(requirement == PasswordRequirement.UPDATE_EMPTY || requirement == PasswordRequirement.UPDATE_SET) {
|
||||
content.getChildren().add(backupExisting);
|
||||
backupExisting.setSelected(true);
|
||||
}
|
||||
|
||||
dialogPane.setContent(content);
|
||||
|
||||
ValidationSupport validationSupport = new ValidationSupport();
|
||||
|
@ -84,6 +91,10 @@ public class WalletPasswordDialog extends Dialog<SecureString> {
|
|||
setResultConverter(dialogButton -> dialogButton == okButtonType ? new SecureString(password.getText()) : null);
|
||||
}
|
||||
|
||||
public boolean isBackupExisting() {
|
||||
return backupExisting.isSelected();
|
||||
}
|
||||
|
||||
public enum PasswordRequirement {
|
||||
LOAD("Please enter the wallet password:", "Unlock"),
|
||||
UPDATE_NEW("Add a password to the wallet?\nLeave empty for none:", "No Password"),
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.sparrowwallet.sparrow.io;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
import com.google.gson.*;
|
||||
import com.sparrowwallet.drongo.ExtendedKey;
|
||||
import com.sparrowwallet.drongo.SecureString;
|
||||
|
@ -19,6 +20,8 @@ import java.lang.reflect.Type;
|
|||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.SecureRandom;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
|
||||
|
@ -27,8 +30,11 @@ import static com.sparrowwallet.drongo.crypto.Argon2KeyDeriver.SPRW1_PARAMETERS;
|
|||
public class Storage {
|
||||
public static final ECKey NO_PASSWORD_KEY = ECKey.fromPublicOnly(ECKey.fromPrivate(Utils.hexToBytes("885e5a09708a167ea356a252387aa7c4893d138d632e296df8fbf5c12798bd28")));
|
||||
|
||||
private static final DateFormat BACKUP_DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||
|
||||
public static final String SPARROW_DIR = ".sparrow";
|
||||
public static final String WALLETS_DIR = "wallets";
|
||||
public static final String WALLETS_BACKUP_DIR = "backup";
|
||||
public static final String HEADER_MAGIC_1 = "SPRW1";
|
||||
private static final int BINARY_HEADER_LENGTH = 28;
|
||||
|
||||
|
@ -157,6 +163,23 @@ public class Storage {
|
|||
outputStream.write(encoded);
|
||||
}
|
||||
|
||||
public void backupWallet() throws IOException {
|
||||
File backupDir = getWalletsBackupDir();
|
||||
|
||||
Date backupDate = new Date();
|
||||
String backupName = walletFile.getName();
|
||||
String dateSuffix = "-" + BACKUP_DATE_FORMAT.format(backupDate);
|
||||
int lastDot = backupName.lastIndexOf('.');
|
||||
if(lastDot > 0) {
|
||||
backupName = backupName.substring(0, lastDot) + dateSuffix + backupName.substring(lastDot);
|
||||
} else {
|
||||
backupName += dateSuffix;
|
||||
}
|
||||
|
||||
File backupFile = new File(backupDir, backupName);
|
||||
Files.copy(walletFile, backupFile);
|
||||
}
|
||||
|
||||
public ECKey getEncryptionPubKey() {
|
||||
return encryptionPubKey;
|
||||
}
|
||||
|
@ -228,6 +251,15 @@ public class Storage {
|
|||
return new File(getWalletsDir(), walletName);
|
||||
}
|
||||
|
||||
public static File getWalletsBackupDir() {
|
||||
File walletsBackupDir = new File(getWalletsDir(), WALLETS_BACKUP_DIR);
|
||||
if(!walletsBackupDir.exists()) {
|
||||
walletsBackupDir.mkdirs();
|
||||
}
|
||||
|
||||
return walletsBackupDir;
|
||||
}
|
||||
|
||||
public static File getWalletsDir() {
|
||||
File walletsDir = new File(getSparrowDir(), WALLETS_DIR);
|
||||
if(!walletsDir.exists()) {
|
||||
|
|
|
@ -26,6 +26,8 @@ import javafx.scene.layout.VBox;
|
|||
import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
import org.controlsfx.glyphfont.Glyph;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import tornadofx.control.DateTimePicker;
|
||||
import tornadofx.control.Field;
|
||||
import tornadofx.control.Fieldset;
|
||||
|
@ -43,6 +45,7 @@ import java.util.*;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
public class HeadersController extends TransactionFormController implements Initializable {
|
||||
private static final Logger log = LoggerFactory.getLogger(HeadersController.class);
|
||||
public static final String LOCKTIME_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
||||
public static final String BLOCK_TIMESTAMP_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss ZZZ";
|
||||
public static final String UNFINALIZED_TXID_CLASS = "unfinalized-txid";
|
||||
|
@ -561,6 +564,7 @@ public class HeadersController extends TransactionFormController implements Init
|
|||
writer.print(headersForm.getPsbt().toBase64String());
|
||||
}
|
||||
} catch(IOException e) {
|
||||
log.error("Error saving PSBT", e);
|
||||
AppController.showErrorDialog("Error saving PSBT", "Cannot write to " + file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
@ -617,6 +621,7 @@ public class HeadersController extends TransactionFormController implements Init
|
|||
unencryptedWallet.sign(headersForm.getPsbt());
|
||||
updateSignedKeystores(headersForm.getSigningWallet());
|
||||
} catch(Exception e) {
|
||||
log.warn("Failed to Sign", e);
|
||||
AppController.showErrorDialog("Failed to Sign", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
@ -707,6 +712,7 @@ public class HeadersController extends TransactionFormController implements Init
|
|||
writer.print(Utils.bytesToHex(finalTx.bitcoinSerialize()));
|
||||
}
|
||||
} catch(IOException e) {
|
||||
log.error("Error saving transaction", e);
|
||||
AppController.showErrorDialog("Error saving transaction", "Cannot write to " + file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ import com.sparrowwallet.sparrow.control.WalletPasswordDialog;
|
|||
import com.sparrowwallet.sparrow.event.SettingsChangedEvent;
|
||||
import com.sparrowwallet.sparrow.event.StorageEvent;
|
||||
import com.sparrowwallet.sparrow.event.TimedEvent;
|
||||
import com.sparrowwallet.sparrow.event.WalletSettingsChangedEvent;
|
||||
import com.sparrowwallet.sparrow.io.Storage;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
|
@ -28,6 +27,8 @@ import javafx.scene.control.*;
|
|||
import javafx.scene.layout.StackPane;
|
||||
import org.controlsfx.control.RangeSlider;
|
||||
import org.controlsfx.tools.Borders;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import tornadofx.control.Fieldset;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -39,6 +40,7 @@ import java.util.ResourceBundle;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
public class SettingsController extends WalletFormController implements Initializable {
|
||||
private static final Logger log = LoggerFactory.getLogger(SettingsController.class);
|
||||
|
||||
@FXML
|
||||
private ComboBox<PolicyType> policyType;
|
||||
|
@ -272,11 +274,24 @@ public class SettingsController extends WalletFormController implements Initiali
|
|||
WalletPasswordDialog dlg = new WalletPasswordDialog(requirement);
|
||||
Optional<SecureString> password = dlg.showAndWait();
|
||||
if(password.isPresent()) {
|
||||
if(dlg.isBackupExisting()) {
|
||||
try {
|
||||
walletForm.saveBackup();
|
||||
} catch(IOException e) {
|
||||
log.error("Error saving wallet backup", e);
|
||||
AppController.showErrorDialog("Error saving wallet backup", e.getMessage());
|
||||
revert.setDisable(false);
|
||||
apply.setDisable(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(password.get().length() == 0) {
|
||||
try {
|
||||
walletForm.getStorage().setEncryptionPubKey(Storage.NO_PASSWORD_KEY);
|
||||
walletForm.saveAndRefresh();
|
||||
} catch (IOException e) {
|
||||
log.error("Error saving wallet", e);
|
||||
AppController.showErrorDialog("Error saving wallet", e.getMessage());
|
||||
revert.setDisable(false);
|
||||
apply.setDisable(false);
|
||||
|
@ -304,6 +319,7 @@ public class SettingsController extends WalletFormController implements Initiali
|
|||
walletForm.getStorage().setEncryptionPubKey(encryptionPubKey);
|
||||
walletForm.saveAndRefresh();
|
||||
} catch (Exception e) {
|
||||
log.error("Error saving wallet", e);
|
||||
AppController.showErrorDialog("Error saving wallet", e.getMessage());
|
||||
revert.setDisable(false);
|
||||
apply.setDisable(false);
|
||||
|
|
|
@ -59,6 +59,10 @@ public class WalletForm {
|
|||
refreshHistory(AppController.getCurrentBlockHeight());
|
||||
}
|
||||
|
||||
public void saveBackup() throws IOException {
|
||||
storage.backupWallet();
|
||||
}
|
||||
|
||||
public void refreshHistory(Integer blockHeight) {
|
||||
Wallet previousWallet = wallet.copy();
|
||||
if(wallet.isValid() && AppController.isOnline()) {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
}
|
||||
|
||||
.form .wideLabelFieldSet.fieldset:horizontal .label-container {
|
||||
-fx-pref-width: 160px;
|
||||
-fx-pref-width: 170px;
|
||||
-fx-pref-height: 25px;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue