Merge pull request #3 from newtonick/insecure-ssl-support
Feature: Add Insecure SSL support for electrum server
This commit is contained in:
commit
5165a3609d
@ -7,9 +7,10 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
3C08EDBF2F5E3A8000C2268E /* BitcoinDevKit in Frameworks */ = {isa = PBXBuildFile; productRef = AA00000200000000000000D0 /* BitcoinDevKit */; };
|
||||
3C08EDC02F5E3A8000C2268E /* URKit in Frameworks */ = {isa = PBXBuildFile; productRef = AA00000500000000000000D0 /* URKit */; };
|
||||
3C08EDC12F5E3A8000C2268E /* URUI in Frameworks */ = {isa = PBXBuildFile; productRef = AA00000800000000000000D0 /* URUI */; };
|
||||
3C1E1C462F7B0D99002FDAE2 /* BitcoinDevKit in Frameworks */ = {isa = PBXBuildFile; productRef = 3C1E1C452F7B0D99002FDAE2 /* BitcoinDevKit */; };
|
||||
3C1E1FA52F7B5F63002FDAE2 /* BitcoinDevKit in Frameworks */ = {isa = PBXBuildFile; productRef = 3C1E1FA42F7B5F63002FDAE2 /* BitcoinDevKit */; };
|
||||
AA0000B100000000000000D0 /* Bbqr in Frameworks */ = {isa = PBXBuildFile; productRef = AA0000B000000000000000D0 /* Bbqr */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@ -59,9 +60,10 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3C1E1C462F7B0D99002FDAE2 /* BitcoinDevKit in Frameworks */,
|
||||
3C08EDC12F5E3A8000C2268E /* URUI in Frameworks */,
|
||||
3C08EDC02F5E3A8000C2268E /* URKit in Frameworks */,
|
||||
3C08EDBF2F5E3A8000C2268E /* BitcoinDevKit in Frameworks */,
|
||||
3C1E1FA52F7B5F63002FDAE2 /* BitcoinDevKit in Frameworks */,
|
||||
AA0000B100000000000000D0 /* Bbqr in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -123,10 +125,11 @@
|
||||
);
|
||||
name = hellbender;
|
||||
packageProductDependencies = (
|
||||
AA00000200000000000000D0 /* BitcoinDevKit */,
|
||||
AA00000500000000000000D0 /* URKit */,
|
||||
AA00000800000000000000D0 /* URUI */,
|
||||
AA0000B000000000000000D0 /* Bbqr */,
|
||||
3C1E1C452F7B0D99002FDAE2 /* BitcoinDevKit */,
|
||||
3C1E1FA42F7B5F63002FDAE2 /* BitcoinDevKit */,
|
||||
);
|
||||
productName = hellbender;
|
||||
productReference = 3C9ACE242F5DED94009B00D0 /* hellbender.app */;
|
||||
@ -211,10 +214,10 @@
|
||||
mainGroup = 3C9ACE1B2F5DED94009B00D0;
|
||||
minimizedProjectReferenceProxies = 1;
|
||||
packageReferences = (
|
||||
AA00000100000000000000D0 /* XCRemoteSwiftPackageReference "bdk-swift" */,
|
||||
AA00000400000000000000D0 /* XCRemoteSwiftPackageReference "URKit" */,
|
||||
AA00000700000000000000D0 /* XCRemoteSwiftPackageReference "URUI" */,
|
||||
AA0000A000000000000000D0 /* XCRemoteSwiftPackageReference "bbqr-swift" */,
|
||||
3C1E1FA32F7B5F63002FDAE2 /* XCRemoteSwiftPackageReference "bdk-swift" */,
|
||||
);
|
||||
preferredProjectObjectVersion = 77;
|
||||
productRefGroup = 3C9ACE252F5DED94009B00D0 /* Products */;
|
||||
@ -589,12 +592,12 @@
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
AA00000100000000000000D0 /* XCRemoteSwiftPackageReference "bdk-swift" */ = {
|
||||
3C1E1FA32F7B5F63002FDAE2 /* XCRemoteSwiftPackageReference "bdk-swift" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/bitcoindevkit/bdk-swift";
|
||||
repositoryURL = "https://github.com/newtonick/bdk-swift";
|
||||
requirement = {
|
||||
kind = exactVersion;
|
||||
version = 2.3.1;
|
||||
version = "2.3.1-ssl-patch";
|
||||
};
|
||||
};
|
||||
AA00000400000000000000D0 /* XCRemoteSwiftPackageReference "URKit" */ = {
|
||||
@ -624,9 +627,13 @@
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
AA00000200000000000000D0 /* BitcoinDevKit */ = {
|
||||
3C1E1C452F7B0D99002FDAE2 /* BitcoinDevKit */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = AA00000100000000000000D0 /* XCRemoteSwiftPackageReference "bdk-swift" */;
|
||||
productName = BitcoinDevKit;
|
||||
};
|
||||
3C1E1FA42F7B5F63002FDAE2 /* BitcoinDevKit */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 3C1E1FA32F7B5F63002FDAE2 /* XCRemoteSwiftPackageReference "bdk-swift" */;
|
||||
productName = BitcoinDevKit;
|
||||
};
|
||||
AA00000500000000000000D0 /* URKit */ = {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"originHash" : "561131c8e974cf1aaf4e7fb48eebaf74a94dabe0b90801de672b9398a0361a37",
|
||||
"originHash" : "11f3c5d73e6615e055e5b9f3671e6180f277a34f298c3f7c6935dcc8dd281089",
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "bbqr-swift",
|
||||
@ -40,10 +40,10 @@
|
||||
{
|
||||
"identity" : "bdk-swift",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/bitcoindevkit/bdk-swift",
|
||||
"location" : "https://github.com/newtonick/bdk-swift",
|
||||
"state" : {
|
||||
"revision" : "c38d7caa06ec26289cb40b1ea42531aea631c47e",
|
||||
"version" : "2.3.1"
|
||||
"revision" : "4660bc83ea6088906edb090652d261e8ed4c09e3",
|
||||
"version" : "2.3.1-ssl-patch"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -17,6 +17,7 @@ final class WalletProfile {
|
||||
var electrumPort: Int
|
||||
var electrumSSL: Int // 0 = network default, 1 = TCP, 2 = SSL
|
||||
var blockExplorerHost: String // empty = mempool.space
|
||||
var electrumAllowInsecureSSL: Bool = false
|
||||
var privacyMode: Bool = false
|
||||
|
||||
@Relationship(deleteRule: .cascade, inverse: \CosignerInfo.wallet)
|
||||
@ -35,6 +36,7 @@ final class WalletProfile {
|
||||
electrumHost: String = "",
|
||||
electrumPort: Int = 0,
|
||||
electrumSSL: Int = 0,
|
||||
electrumAllowInsecureSSL: Bool = false,
|
||||
blockExplorerHost: String = "",
|
||||
privacyMode: Bool = false
|
||||
) {
|
||||
@ -51,6 +53,7 @@ final class WalletProfile {
|
||||
self.electrumHost = electrumHost
|
||||
self.electrumPort = electrumPort
|
||||
self.electrumSSL = electrumSSL
|
||||
self.electrumAllowInsecureSSL = electrumAllowInsecureSSL
|
||||
self.blockExplorerHost = blockExplorerHost
|
||||
self.privacyMode = privacyMode
|
||||
cosigners = []
|
||||
@ -69,7 +72,7 @@ final class WalletProfile {
|
||||
case 2: true // SSL
|
||||
default: net.usesSSL // 0 = network default
|
||||
}
|
||||
return ElectrumConfig(host: host, port: port, useSSL: ssl)
|
||||
return ElectrumConfig(host: host, port: port, useSSL: ssl, allowInsecureSSL: electrumAllowInsecureSSL)
|
||||
}
|
||||
|
||||
var multisigDescription: String {
|
||||
|
||||
@ -267,7 +267,8 @@ final class BitcoinService {
|
||||
addToLog("Connecting to Electrum: \(config.url)")
|
||||
do {
|
||||
let url = config.url
|
||||
electrumClient = try await Task.detached { try ElectrumClient(url: url) }.value
|
||||
let validateDomain = !config.allowInsecureSSL
|
||||
electrumClient = try await Task.detached { try ElectrumClient(url: url, validateDomain: validateDomain) }.value
|
||||
electrumConnectionError = nil
|
||||
addToLog("Electrum client initialized")
|
||||
} catch {
|
||||
@ -304,7 +305,8 @@ final class BitcoinService {
|
||||
let config = profile.electrumConfig
|
||||
addToLog("Re-initializing Electrum client: \(config.url)")
|
||||
let reconnectURL = config.url
|
||||
electrumClient = try await Task.detached { try ElectrumClient(url: reconnectURL) }.value
|
||||
let validateDomain = !config.allowInsecureSSL
|
||||
electrumClient = try await Task.detached { try ElectrumClient(url: reconnectURL, validateDomain: validateDomain) }.value
|
||||
electrumConnectionError = nil
|
||||
}
|
||||
|
||||
@ -459,13 +461,14 @@ final class BitcoinService {
|
||||
@discardableResult
|
||||
func testElectrumConnection(config: ElectrumConfig) async throws -> UInt32 {
|
||||
// Pre-check SSL certificate before handing off to BDK
|
||||
if config.useSSL {
|
||||
if config.useSSL, !config.allowInsecureSSL {
|
||||
try await Self.validateTLSCertificate(host: config.host, port: config.port)
|
||||
}
|
||||
|
||||
let url = config.url
|
||||
let validateDomain = !config.allowInsecureSSL
|
||||
let header = try await Task.detached {
|
||||
let client = try ElectrumClient(url: url)
|
||||
let client = try ElectrumClient(url: url, validateDomain: validateDomain)
|
||||
return try client.blockHeadersSubscribe()
|
||||
}.value
|
||||
return UInt32(header.height)
|
||||
|
||||
@ -4,21 +4,24 @@ struct ElectrumConfig: Equatable {
|
||||
var host: String
|
||||
var port: UInt16
|
||||
var useSSL: Bool
|
||||
var allowInsecureSSL: Bool
|
||||
|
||||
var url: String {
|
||||
let proto = useSSL ? "ssl" : "tcp"
|
||||
return "\(proto)://\(host):\(port)"
|
||||
}
|
||||
|
||||
init(host: String, port: UInt16, useSSL: Bool) {
|
||||
init(host: String, port: UInt16, useSSL: Bool, allowInsecureSSL: Bool = false) {
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.useSSL = useSSL
|
||||
self.allowInsecureSSL = allowInsecureSSL
|
||||
}
|
||||
|
||||
init(network: BitcoinNetwork) {
|
||||
host = network.defaultElectrumHost ?? ""
|
||||
port = network.defaultElectrumPort
|
||||
useSSL = network.usesSSL
|
||||
allowInsecureSSL = false
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,6 +50,7 @@ final class SetupWizardViewModel {
|
||||
var electrumHost: String = ""
|
||||
var electrumPort: String = ""
|
||||
var electrumSSL: Int = 0 // 0 = network default, 1 = TCP, 2 = SSL
|
||||
var electrumAllowInsecureSSL: Bool = false
|
||||
|
||||
/// Returns an error message if the descriptor contains keys that don't match the selected network, nil otherwise.
|
||||
var descriptorNetworkMismatchError: String? {
|
||||
@ -449,6 +450,7 @@ final class SetupWizardViewModel {
|
||||
electrumHost: electrumHost.trimmingCharacters(in: .whitespaces),
|
||||
electrumPort: Int(electrumPort) ?? 0,
|
||||
electrumSSL: electrumSSL,
|
||||
electrumAllowInsecureSSL: electrumAllowInsecureSSL,
|
||||
blockExplorerHost: blockExplorerHost.trimmingCharacters(in: .whitespaces)
|
||||
)
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@ struct WalletInfoView: View {
|
||||
@State private var connectionTestResult: String?
|
||||
@State private var blockExplorerText: String = ""
|
||||
@State private var initialElectrumConfig: ElectrumConfig?
|
||||
@State private var showInsecureSSLAlert = false
|
||||
@State private var showDescriptorQR = false
|
||||
@State private var showDeleteConfirmation = false
|
||||
@State private var showDescriptorPDF = false
|
||||
@ -200,7 +201,12 @@ struct WalletInfoView: View {
|
||||
default: wallet.bitcoinNetwork.usesSSL ? 2 : 1
|
||||
}
|
||||
},
|
||||
set: { wallet.electrumSSL = $0 }
|
||||
set: {
|
||||
wallet.electrumSSL = $0
|
||||
if $0 != 2 {
|
||||
wallet.electrumAllowInsecureSSL = false
|
||||
}
|
||||
}
|
||||
)) {
|
||||
Text("TCP").tag(1)
|
||||
Text("SSL").tag(2)
|
||||
@ -208,6 +214,24 @@ struct WalletInfoView: View {
|
||||
.pickerStyle(.segmented)
|
||||
}
|
||||
|
||||
if wallet.electrumSSL == 2 || (wallet.electrumSSL == 0 && wallet.bitcoinNetwork.usesSSL) {
|
||||
Toggle(isOn: Binding(
|
||||
get: { wallet.electrumAllowInsecureSSL },
|
||||
set: { newValue in
|
||||
if newValue {
|
||||
showInsecureSSLAlert = true
|
||||
} else {
|
||||
wallet.electrumAllowInsecureSSL = false
|
||||
}
|
||||
}
|
||||
)) {
|
||||
Text("Allow insecure SSL")
|
||||
.font(.hbBody(13))
|
||||
.foregroundStyle(Color.hbTextPrimary)
|
||||
}
|
||||
.tint(Color.hbBitcoinOrange)
|
||||
}
|
||||
|
||||
if let result = connectionTestResult {
|
||||
Text(result)
|
||||
.font(.hbBody(13))
|
||||
@ -426,6 +450,14 @@ struct WalletInfoView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
.alert("Allow Insecure SSL?", isPresented: $showInsecureSSLAlert) {
|
||||
Button("Cancel", role: .cancel) {}
|
||||
Button("Allow", role: .destructive) {
|
||||
wallet.electrumAllowInsecureSSL = true
|
||||
}
|
||||
} message: {
|
||||
Text("This removes the requirement to verify that the server is who it claims to be. The connection will still be encrypted, but self-signed, expired, or invalid certificates will be accepted.")
|
||||
}
|
||||
.sheet(isPresented: $showEditCosigners) {
|
||||
EditCosignersView(wallet: wallet)
|
||||
}
|
||||
@ -460,6 +492,7 @@ struct WalletInfoView: View {
|
||||
wallet.electrumHost = ""
|
||||
wallet.electrumPort = 0
|
||||
wallet.electrumSSL = 0
|
||||
wallet.electrumAllowInsecureSSL = false
|
||||
electrumHostText = ""
|
||||
electrumPortText = ""
|
||||
connectionTestResult = nil
|
||||
|
||||
@ -2,6 +2,15 @@ import SwiftUI
|
||||
|
||||
struct ElectrumServerSetupSection: View {
|
||||
@Bindable var viewModel: SetupWizardViewModel
|
||||
@State private var showInsecureSSLAlert = false
|
||||
|
||||
private var isSSLSelected: Bool {
|
||||
switch viewModel.electrumSSL {
|
||||
case 1: false
|
||||
case 2: true
|
||||
default: viewModel.network.usesSSL
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 12) {
|
||||
@ -50,7 +59,12 @@ struct ElectrumServerSetupSection: View {
|
||||
default: viewModel.network.usesSSL ? 2 : 1
|
||||
}
|
||||
},
|
||||
set: { viewModel.electrumSSL = $0 }
|
||||
set: {
|
||||
viewModel.electrumSSL = $0
|
||||
if $0 != 2 {
|
||||
viewModel.electrumAllowInsecureSSL = false
|
||||
}
|
||||
}
|
||||
)) {
|
||||
Text("TCP").tag(1)
|
||||
Text("SSL").tag(2)
|
||||
@ -59,6 +73,24 @@ struct ElectrumServerSetupSection: View {
|
||||
}
|
||||
}
|
||||
|
||||
if isSSLSelected {
|
||||
Toggle(isOn: Binding(
|
||||
get: { viewModel.electrumAllowInsecureSSL },
|
||||
set: { newValue in
|
||||
if newValue {
|
||||
showInsecureSSLAlert = true
|
||||
} else {
|
||||
viewModel.electrumAllowInsecureSSL = false
|
||||
}
|
||||
}
|
||||
)) {
|
||||
Text("Allow insecure SSL")
|
||||
.font(.hbBody(13))
|
||||
.foregroundStyle(Color.hbTextPrimary)
|
||||
}
|
||||
.tint(Color.hbBitcoinOrange)
|
||||
}
|
||||
|
||||
if viewModel.network.defaultElectrumHost != nil {
|
||||
Text("Leave blank to use defaults for \(viewModel.network.displayName)")
|
||||
.font(.hbBody(11))
|
||||
@ -70,6 +102,14 @@ struct ElectrumServerSetupSection: View {
|
||||
}
|
||||
}
|
||||
.hbCard()
|
||||
.alert("Allow Insecure SSL?", isPresented: $showInsecureSSLAlert) {
|
||||
Button("Cancel", role: .cancel) {}
|
||||
Button("Allow", role: .destructive) {
|
||||
viewModel.electrumAllowInsecureSSL = true
|
||||
}
|
||||
} message: {
|
||||
Text("This removes the requirement to verify that the server is who it claims to be. The connection will still be encrypted, but self-signed, expired, or invalid certificates will be accepted.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user