add public electrum server type

This commit is contained in:
Craig Raw
2021-02-16 16:38:36 +02:00
parent 48a63c25d2
commit 454e4b4c4b
9 changed files with 221 additions and 11 deletions
@@ -542,7 +542,18 @@ public class AppController implements Initializable {
}
private void setServerToggleTooltip(Integer currentBlockHeight) {
serverToggle.setTooltip(new Tooltip(AppServices.isConnected() ? "Connected to " + Config.get().getServerAddress() + (currentBlockHeight != null ? " at height " + currentBlockHeight : "") : "Disconnected"));
Tooltip tooltip = new Tooltip(getServerToggleTooltipText(currentBlockHeight));
tooltip.setShowDuration(Duration.seconds(15));
serverToggle.setTooltip(tooltip);
}
private String getServerToggleTooltipText(Integer currentBlockHeight) {
if(AppServices.isConnected()) {
return "Connected to " + Config.get().getServerAddress() + (currentBlockHeight != null ? " at height " + currentBlockHeight : "") +
(Config.get().getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER ? "\nWarning! You are connected to a public server and sharing your transaction data with it.\nFor better privacy, consider using your own Bitcoin Core node or private Electrum server." : "");
}
return "Disconnected";
}
public void newWallet(ActionEvent event) {
@@ -1069,6 +1080,12 @@ public class AppController implements Initializable {
}
public void setServerType(ServerType serverType) {
if(serverType == ServerType.PUBLIC_ELECTRUM_SERVER && !serverToggle.getStyleClass().contains("public-server")) {
serverToggle.getStyleClass().add("public-server");
} else {
serverToggle.getStyleClass().remove("public-server");
}
if(serverType == ServerType.BITCOIN_CORE && !serverToggle.getStyleClass().contains("core-server")) {
serverToggle.getStyleClass().add("core-server");
} else {
@@ -38,6 +38,7 @@ public class Config {
private File hwi;
private boolean hdCapture;
private ServerType serverType;
private String publicElectrumServer;
private String coreServer;
private CoreAuthType coreAuthType;
private File coreDataDir;
@@ -275,7 +276,7 @@ public class Config {
}
public String getServerAddress() {
return getServerType() == ServerType.BITCOIN_CORE ? getCoreServer() : getElectrumServer();
return getServerType() == ServerType.BITCOIN_CORE ? getCoreServer() : (getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER ? getPublicElectrumServer() : getElectrumServer());
}
public boolean requiresTor() {
@@ -291,6 +292,15 @@ public class Config {
return protocol.isOnionAddress(protocol.getServerHostAndPort(getServerAddress()));
}
public String getPublicElectrumServer() {
return publicElectrumServer;
}
public void setPublicElectrumServer(String publicElectrumServer) {
this.publicElectrumServer = publicElectrumServer;
flush();
}
public String getCoreServer() {
return coreServer;
}
@@ -53,7 +53,10 @@ public class ElectrumServer {
File electrumServerCert = null;
String proxyServer = null;
if(Config.get().getServerType() == ServerType.BITCOIN_CORE) {
if(Config.get().getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER) {
electrumServer = Config.get().getPublicElectrumServer();
proxyServer = Config.get().getProxyServer();
} else if(Config.get().getServerType() == ServerType.BITCOIN_CORE) {
if(bwtElectrumServer == null) {
throw new ServerConfigException("Could not connect to Bitcoin Core RPC");
}
@@ -0,0 +1,38 @@
package com.sparrowwallet.sparrow.net;
public enum PublicElectrumServer {
BLOCKSTREAM_INFO("blockstream.info", "ssl://blockstream.info:700"),
ELECTRUM_BLOCKSTREAM_INFO("electrum.blockstream.info", "ssl://electrum.blockstream.info:50002"),
LUKECHILDS_CO("bitcoin.lukechilds.co", "ssl://bitcoin.lukechilds.co:50002");
PublicElectrumServer(String name, String url) {
this.name = name;
this.url = url;
}
private final String name;
private final String url;
public String getName() {
return name;
}
public String getUrl() {
return url;
}
public static PublicElectrumServer fromUrl(String url) {
for(PublicElectrumServer server : values()) {
if(server.url.equals(url)) {
return server;
}
}
return null;
}
@Override
public String toString() {
return name;
}
}
@@ -1,7 +1,7 @@
package com.sparrowwallet.sparrow.net;
public enum ServerType {
BITCOIN_CORE("Bitcoin Core"), ELECTRUM_SERVER("Electrum Server");
BITCOIN_CORE("Bitcoin Core"), ELECTRUM_SERVER("Private Electrum"), PUBLIC_ELECTRUM_SERVER("Public Electrum");
private final String name;
@@ -46,7 +46,7 @@ public class PreferencesDialog extends Dialog<Boolean> {
dialogPane.getButtonTypes().addAll(newWalletButtonType);
}
dialogPane.setPrefWidth(650);
dialogPane.setPrefWidth(710);
dialogPane.setPrefHeight(600);
preferencesController.reconnectOnClosingProperty().set(AppServices.isConnecting() || AppServices.isConnected());
@@ -23,6 +23,7 @@ import javafx.stage.Stage;
import javafx.util.Duration;
import net.freehaven.tor.control.TorControlError;
import org.berndpruenster.netlayer.tor.Tor;
import org.controlsfx.control.SegmentedButton;
import org.controlsfx.glyphfont.Glyph;
import org.controlsfx.validation.ValidationResult;
import org.controlsfx.validation.ValidationSupport;
@@ -41,6 +42,7 @@ import java.security.cert.CertificateFactory;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Random;
public class ServerPreferencesController extends PreferencesDetailController {
private static final Logger log = LoggerFactory.getLogger(ServerPreferencesController.class);
@@ -48,6 +50,27 @@ public class ServerPreferencesController extends PreferencesDetailController {
@FXML
private ToggleGroup serverTypeToggleGroup;
@FXML
private SegmentedButton serverTypeSegmentedButton;
@FXML
private ToggleButton publicElectrumToggle;
@FXML
private Form publicElectrumForm;
@FXML
private ComboBox<PublicElectrumServer> publicElectrumServer;
@FXML
private UnlabeledToggleSwitch publicUseProxy;
@FXML
private TextField publicProxyHost;
@FXML
private TextField publicProxyPort;
@FXML
private Form coreForm;
@@ -135,13 +158,15 @@ public class ServerPreferencesController extends PreferencesDetailController {
Platform.runLater(this::setupValidation);
publicElectrumForm.managedProperty().bind(publicElectrumForm.visibleProperty());
coreForm.managedProperty().bind(coreForm.visibleProperty());
electrumForm.managedProperty().bind(electrumForm.visibleProperty());
coreForm.visibleProperty().bind(electrumForm.visibleProperty().not());
serverTypeToggleGroup.selectedToggleProperty().addListener((observable, oldValue, newValue) -> {
if(serverTypeToggleGroup.getSelectedToggle() != null) {
ServerType existingType = config.getServerType();
ServerType serverType = (ServerType)newValue.getUserData();
publicElectrumForm.setVisible(serverType == ServerType.PUBLIC_ELECTRUM_SERVER);
coreForm.setVisible(serverType == ServerType.BITCOIN_CORE);
electrumForm.setVisible(serverType == ServerType.ELECTRUM_SERVER);
config.setServerType(serverType);
testConnection.setGraphic(getGlyph(FontAwesome5.Glyph.QUESTION_CIRCLE, ""));
@@ -153,12 +178,26 @@ public class ServerPreferencesController extends PreferencesDetailController {
oldValue.setSelected(true);
}
});
ServerType serverType = config.getServerType() != null ? config.getServerType() : (config.getCoreServer() == null && config.getElectrumServer() != null ? ServerType.ELECTRUM_SERVER : ServerType.BITCOIN_CORE);
ServerType serverType = config.getServerType() != null ?
(config.getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER && Network.get() != Network.MAINNET ? ServerType.BITCOIN_CORE : config.getServerType()) :
(config.getCoreServer() == null && config.getElectrumServer() != null ? ServerType.ELECTRUM_SERVER :
(config.getCoreServer() != null || Network.get() != Network.MAINNET ? ServerType.BITCOIN_CORE : ServerType.PUBLIC_ELECTRUM_SERVER));
if(Network.get() != Network.MAINNET) {
serverTypeSegmentedButton.getButtons().remove(publicElectrumToggle);
serverTypeToggleGroup.getToggles().remove(publicElectrumToggle);
}
serverTypeToggleGroup.selectToggle(serverTypeToggleGroup.getToggles().stream().filter(toggle -> toggle.getUserData() == serverType).findFirst().orElse(null));
publicElectrumServer.getSelectionModel().selectedItemProperty().addListener(getPublicElectrumServerListener(config));
publicUseProxy.selectedProperty().bindBidirectional(useProxy.selectedProperty());
publicProxyHost.textProperty().bindBidirectional(proxyHost.textProperty());
publicProxyPort.textProperty().bindBidirectional(proxyPort.textProperty());
corePort.setTextFormatter(new TextFieldValidator(TextFieldValidator.ValidationModus.MAX_INTEGERS, 5).getFormatter());
electrumPort.setTextFormatter(new TextFieldValidator(TextFieldValidator.ValidationModus.MAX_INTEGERS, 5).getFormatter());
proxyPort.setTextFormatter(new TextFieldValidator(TextFieldValidator.ValidationModus.MAX_INTEGERS, 5).getFormatter());
publicProxyPort.setTextFormatter(new TextFieldValidator(TextFieldValidator.ValidationModus.MAX_INTEGERS, 5).getFormatter());
coreHost.textProperty().addListener(getBitcoinCoreListener(config));
corePort.textProperty().addListener(getBitcoinCoreListener(config));
@@ -245,6 +284,8 @@ public class ServerPreferencesController extends PreferencesDetailController {
proxyHost.setText(proxyHost.getText().trim());
proxyHost.setDisable(!newValue);
proxyPort.setDisable(!newValue);
publicProxyHost.setDisable(!newValue);
publicProxyPort.setDisable(!newValue);
});
boolean isConnected = AppServices.isConnecting() || AppServices.isConnected();
@@ -277,6 +318,13 @@ public class ServerPreferencesController extends PreferencesDetailController {
testConnection.setVisible(true);
});
PublicElectrumServer configPublicElectrumServer = PublicElectrumServer.fromUrl(config.getPublicElectrumServer());
if(configPublicElectrumServer == null) {
publicElectrumServer.setValue(PublicElectrumServer.values()[new Random().nextInt(PublicElectrumServer.values().length)]);
} else {
publicElectrumServer.setValue(configPublicElectrumServer);
}
String coreServer = config.getCoreServer();
if(coreServer != null) {
Protocol protocol = Protocol.getProtocol(coreServer);
@@ -340,6 +388,8 @@ public class ServerPreferencesController extends PreferencesDetailController {
useProxy.setSelected(config.isUseProxy());
proxyHost.setDisable(!config.isUseProxy());
proxyPort.setDisable(!config.isUseProxy());
publicProxyHost.setDisable(!config.isUseProxy());
publicProxyPort.setDisable(!config.isUseProxy());
String proxyServer = config.getProxyServer();
if(proxyServer != null) {
@@ -407,6 +457,11 @@ public class ServerPreferencesController extends PreferencesDetailController {
private void setFieldsEditable(boolean editable) {
serverTypeToggleGroup.getToggles().forEach(toggle -> ((ToggleButton)toggle).setDisable(!editable));
publicElectrumServer.setDisable(!editable);
publicUseProxy.setDisable(!editable);
publicProxyHost.setDisable(!editable);
publicProxyPort.setDisable(!editable);
coreHost.setDisable(!editable);
corePort.setDisable(!editable);
coreAuthToggleGroup.getToggles().forEach(toggle -> ((ToggleButton)toggle).setDisable(!editable));
@@ -455,6 +510,15 @@ public class ServerPreferencesController extends PreferencesDetailController {
}
private void setupValidation() {
validationSupport.registerValidator(publicProxyHost, Validator.combine(
(Control c, String newValue) -> ValidationResult.fromErrorIf( c, "Proxy host required", publicUseProxy.isSelected() && newValue.isEmpty()),
(Control c, String newValue) -> ValidationResult.fromErrorIf( c, "Invalid host name", getHost(newValue) == null)
));
validationSupport.registerValidator(publicProxyPort, Validator.combine(
(Control c, String newValue) -> ValidationResult.fromErrorIf( c, "Invalid proxy port", !newValue.isEmpty() && !isValidPort(Integer.parseInt(newValue)))
));
validationSupport.registerValidator(coreHost, Validator.combine(
(Control c, String newValue) -> ValidationResult.fromErrorIf( c, "Invalid Core host", getHost(newValue) == null)
));
@@ -499,6 +563,13 @@ public class ServerPreferencesController extends PreferencesDetailController {
validationSupport.setValidationDecorator(new StyleClassValidationDecoration());
}
@NotNull
private ChangeListener<PublicElectrumServer> getPublicElectrumServerListener(Config config) {
return (observable, oldValue, newValue) -> {
config.setPublicElectrumServer(newValue.getUrl());
};
}
@NotNull
private ChangeListener<String> getBitcoinCoreListener(Config config) {
return (observable, oldValue, newValue) -> {