finalising wallet settings

This commit is contained in:
Craig Raw 2020-05-13 12:47:21 +02:00
parent 84888b4a43
commit bc5690346c
17 changed files with 101 additions and 22 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

2
drongo

@ -1 +1 @@
Subproject commit b951f79cfded507112cc7f213567c6a43c00e7e8
Subproject commit 766a986abb72ea84317a405b93055abc3d1eaf22

BIN
src/.DS_Store vendored Normal file

Binary file not shown.

View file

@ -259,7 +259,11 @@ public class AppController implements Initializable {
public Tab addWalletTab(File walletFile, ECKey encryptionPubKey, Wallet wallet) {
try {
Tab tab = new Tab(walletFile.getName());
String name = walletFile.getName();
if(name.endsWith(".json")) {
name = name.substring(0, name.lastIndexOf('.'));
}
Tab tab = new Tab(name);
TabData tabData = new TabData(TabData.TabType.WALLET);
tab.setUserData(tabData);
tab.setContextMenu(getTabContextMenu(tab));

View file

@ -40,8 +40,8 @@ public class MainApp extends Application {
wallet.setPolicyType(PolicyType.SINGLE);
wallet.setScriptType(ScriptType.P2WPKH);
KeystoreImportDialog dlg = new KeystoreImportDialog(wallet);
dlg.showAndWait();
// KeystoreImportDialog dlg = new KeystoreImportDialog(wallet);
// dlg.showAndWait();
stage.show();
}

View file

@ -62,6 +62,16 @@ public class Storage {
throw new IOException("Could not create folder " + parent);
}
if(!file.getName().endsWith(".json")) {
File jsonFile = new File(parent, file.getName() + ".json");
if(file.exists()) {
if(!file.renameTo(jsonFile)) {
throw new IOException("Could not rename " + file.getName() + " to " + jsonFile.getName());
}
}
file = jsonFile;
}
Writer writer = new FileWriter(file);
gson.toJson(wallet, writer);
writer.close();
@ -73,6 +83,16 @@ public class Storage {
throw new IOException("Could not create folder " + parent);
}
if(file.getName().endsWith(".json")) {
File noJsonFile = new File(parent, file.getName().substring(0, file.getName().lastIndexOf('.')));
if(file.exists()) {
if(!file.renameTo(noJsonFile)) {
throw new IOException("Could not rename " + file.getName() + " to " + noJsonFile.getName());
}
}
file = noJsonFile;
}
OutputStreamWriter writer = new OutputStreamWriter(new DeflaterOutputStream(new ECIESOutputStream(new FileOutputStream(file), encryptionKey, getEncryptionMagic())), StandardCharsets.UTF_8);
gson.toJson(wallet, writer);
writer.close();

View file

@ -63,6 +63,9 @@ public class KeystoreController extends WalletFormController implements Initiali
Platform.runLater(this::setupValidation);
selectSourcePane.managedProperty().bind(selectSourcePane.visibleProperty());
if(keystore.isValid()) {
selectSourcePane.setVisible(false);
}
updateType();

View file

@ -88,14 +88,14 @@ public class SettingsController extends WalletFormController implements Initiali
scriptType.getSelectionModel().select(policyType.getDefaultScriptType());
}
if(oldValue != null) {
clearKeystoreTabs();
}
multisigFieldset.setVisible(policyType.equals(PolicyType.MULTI));
if(policyType.equals(PolicyType.MULTI)) {
totalKeystores.unbind();
totalKeystores.set(0);
totalKeystores.bind(multisigControl.highValueProperty());
} else {
totalKeystores.unbind();
totalKeystores.set(0);
totalKeystores.set(1);
}
});
@ -159,9 +159,9 @@ public class SettingsController extends WalletFormController implements Initiali
apply.setOnAction(event -> {
try {
Optional<ECKey> optionalPubKey = askForWalletPassword(walletForm.getEncryptionPubKey());
Optional<ECKey> optionalPubKey = requestEncryption(walletForm.getEncryptionPubKey());
if(optionalPubKey.isPresent()) {
walletForm.setEncryptionPubKey(ECKey.fromPublicOnly(optionalPubKey.get()));
walletForm.setEncryptionPubKey(optionalPubKey.get());
walletForm.save();
revert.setDisable(true);
apply.setDisable(true);
@ -175,6 +175,11 @@ public class SettingsController extends WalletFormController implements Initiali
setFieldsFromWallet(walletForm.getWallet());
}
private void clearKeystoreTabs() {
totalKeystores.unbind();
totalKeystores.set(0);
}
private void setFieldsFromWallet(Wallet wallet) {
if(wallet.getPolicyType() == null) {
wallet.setPolicyType(PolicyType.SINGLE);
@ -261,7 +266,7 @@ public class SettingsController extends WalletFormController implements Initiali
Platform.runLater(() -> apply.setDisable(!tabsValidate()));
}
private Optional<ECKey> askForWalletPassword(ECKey existingPubKey) {
private Optional<ECKey> requestEncryption(ECKey existingPubKey) {
WalletPasswordDialog.PasswordRequirement requirement;
if(existingPubKey == null) {
requirement = WalletPasswordDialog.PasswordRequirement.UPDATE_NEW;
@ -280,16 +285,14 @@ public class SettingsController extends WalletFormController implements Initiali
ECKey encryptionFullKey = ECIESKeyCrypter.deriveECKey(password.get());
ECKey encryptionPubKey = ECKey.fromPublicOnly(encryptionFullKey);
if(existingPubKey != null) {
if(WalletForm.NO_PASSWORD_KEY.equals(existingPubKey) || existingPubKey.equals(encryptionPubKey)) {
return Optional.of(encryptionPubKey);
} else {
if(existingPubKey != null && !WalletForm.NO_PASSWORD_KEY.equals(existingPubKey) && !existingPubKey.equals(encryptionPubKey)) {
AppController.showErrorDialog("Incorrect Password", "The password was incorrect.");
return Optional.empty();
}
}
return Optional.of(encryptionFullKey);
walletForm.getWallet().encrypt(password.get());
return Optional.of(encryptionPubKey);
}
return Optional.empty();

View file

@ -2,10 +2,13 @@ package com.sparrowwallet.sparrow.wallet;
import com.sparrowwallet.sparrow.AppController;
import com.sparrowwallet.sparrow.EventManager;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
@ -61,5 +64,25 @@ public class WalletController extends WalletFormController implements Initializa
throw new IllegalStateException("Can't find pane", e);
}
});
if(!walletForm.getWallet().isValid()) {
for(Toggle toggle : walletMenu.getToggles()) {
if(toggle.getUserData().equals(Function.SETTINGS)) {
toggle.setSelected(true);
} else {
((ToggleButton)toggle).setDisable(true);
}
}
}
}
public void selectFunction(Function function) {
Platform.runLater(() -> {
for(Toggle toggle : walletMenu.getToggles()) {
if(toggle.getUserData().equals(function)) {
toggle.setSelected(true);
}
}
});
}
}

View file

@ -20,6 +20,11 @@
-fx-background-color: #1e88cf;
}
.list-item:disabled {
-fx-background-color: #a0a1a7;
-fx-opacity: 1;
}
#walletPane {
-fx-background-color: -fx-background;
}

BIN
src/test/.DS_Store vendored Normal file

Binary file not shown.

View file

@ -1,14 +1,15 @@
package com.sparrowwallet.sparrow.io;
import com.sparrowwallet.drongo.Utils;
import com.sparrowwallet.drongo.crypto.ECIESKeyCrypter;
import com.sparrowwallet.drongo.crypto.ECKey;
import com.sparrowwallet.drongo.policy.PolicyType;
import com.sparrowwallet.drongo.protocol.ScriptType;
import com.sparrowwallet.drongo.wallet.Wallet;
import org.junit.Assert;
import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.*;
public class StorageTest extends IoTest {
@Test
@ -18,6 +19,25 @@ public class StorageTest extends IoTest {
Assert.assertTrue(wallet.isValid());
}
@Test
public void loadSeedWallet() throws IOException {
ECKey decryptionKey = ECIESKeyCrypter.deriveECKey("pass");
Wallet wallet = Storage.getStorage().loadWallet(getFile("sparrow-single-seed-wallet"), decryptionKey);
Assert.assertTrue(wallet.isValid());
Assert.assertEquals("testa1", wallet.getName());
Assert.assertEquals(PolicyType.SINGLE, wallet.getPolicyType());
Assert.assertEquals(ScriptType.P2WPKH, wallet.getScriptType());
Assert.assertEquals(1, wallet.getDefaultPolicy().getNumSignaturesRequired());
Assert.assertEquals("pkh(60bcd3a7)", wallet.getDefaultPolicy().getMiniscript().getScript());
Assert.assertEquals("60bcd3a7", wallet.getKeystores().get(0).getKeyDerivation().getMasterFingerprint());
Assert.assertEquals("m/84'/0'/0'", wallet.getKeystores().get(0).getKeyDerivation().getDerivationPath());
Assert.assertEquals("xpub6BrhGFTWPd3DQaGP7p5zTQkE5nqVbaRs23HNae8jAoNJYS2NGa9Sgpeqv1dS5ygwD4sQfwqLCk5qXRK45FTgnqHRcrPnts3Qgh78BZrnoMn", wallet.getKeystores().get(0).getExtendedPublicKey().toString());
Assert.assertEquals("b0e161bff5f589e74b20d9cd260702a6a1e6e1ab3ba4ce764f388dd8f360a1ccdb21099a2f22757ca72f9bde3a34b97a31fb513fb8931c821b0d25798e450b6a57dc106973849ca586b50b2db2840adc", Utils.bytesToHex(wallet.getKeystores().get(0).getSeed().getEncryptedSeedData().getEncryptedBytes()));
Assert.assertNull(wallet.getKeystores().get(0).getSeed().getSeedBytes());
}
@Test
public void saveWallet() throws IOException {
ECKey decryptionKey = ECIESKeyCrypter.deriveECKey("pass");

BIN
src/test/resources/.DS_Store vendored Normal file

Binary file not shown.

BIN
src/test/resources/com/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1 @@
QklFMQOXQWixo1F4kqJjn/7UeGDmbpNdMGPUP+vzRWdUE2vOcHfejUklKAzq1cTpK0mMEOOHCZ+yg0LxF29KMFQpoSpRTl6GRjnmpGIu3HPuu7bjbL6GvZQXFkvmK+9zsrllxZl6sYMjP4zoHJH6JgL4qGFpnM9n/mtOGYAuOw7zj4fm10teHLLgJLpkZ4ze0n/t8QhbyPPkeEoNmw/gt1PrwNDneKtALCNNdGopEq0QWD15OCEY7fSIfu0K1VO9oMZpOHs78p335Ka7bRRjuq+RWvZLz/X5hb9zVlFIu+KLW/preykMbfg4UiPcVHfc9wSLsmqZe9btYa3yxsem9xRW7J4gXMr7uqMTw/dlrK6XNg0wBXH6cuBed3M6Nu72Hz0OU+M64HEUnsGRYLgz3XcsZAU7+jeUQp6D8sVjH7GsPFIdZl0wzhWNHsgQGLoGXnWyvatsPsklW9BQ5U1d0PxeLxWppwj42Y7YA0+O3BrN7lUmD6xATNt9/xwVotPIllXT84r/OpzFbULzSBZ0uwwV+4tdCOa7FHPUed5gXZCPk6lhPHkz2N6Ehm3WGOQBQsoTfObefYUjHhB+a6Rpggm7QgkLhBEtgy7sPCV39fnRYM52uOwDUhNB8K/h/RadkMX51eXtbx23+LU+jM8zpi4T6yLM1Rq8H9YZ+rJXUIZPOHwX2ytnXkwHcYanThhxvQa55v3vbC5X/JFVSA+yik1CejXctjv9I++5mCCJtGpk/USAWzIb3nhKURPi/a3sg7y/n47s79AxvzvLndlY96UIaI1QVaNoaoJtt1+cBLzrXGlc4hChIqloZN4GJ4F1KabDuyXwagGvsd14zTH6ELAprmJkrd0l9JNTEBrJJbRqFEZj7CwrREyUkxGaiskca+ZyHm4LuwKo/6m5dKgiqyeMUB6WdZFXDERSp9ldf8n+o6OSxolEq4wWxM2uGdbHZTBsORq0JyIS4CQcfiC4UQoXJnQpGAfKWNsc1jS/x0BlV/9n2rhGxC0LRQZ2YbtLwfwd138=