Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions hellbender.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 */;
Expand Down Expand Up @@ -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 */;
Expand Down Expand Up @@ -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" */ = {
Expand Down Expand Up @@ -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 */ = {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion hellbender/Models/WalletProfile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -35,6 +36,7 @@ final class WalletProfile {
electrumHost: String = "",
electrumPort: Int = 0,
electrumSSL: Int = 0,
electrumAllowInsecureSSL: Bool = false,
blockExplorerHost: String = "",
privacyMode: Bool = false
) {
Expand All @@ -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 = []
Expand All @@ -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 {
Expand Down
11 changes: 7 additions & 4 deletions hellbender/Services/BitcoinService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,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 {
Expand Down Expand Up @@ -301,7 +302,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
}

Expand Down Expand Up @@ -453,13 +455,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)
Expand Down
5 changes: 4 additions & 1 deletion hellbender/Services/ElectrumConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
2 changes: 2 additions & 0 deletions hellbender/ViewModels/SetupWizardViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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? {
Expand Down Expand Up @@ -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)
)

Expand Down
35 changes: 34 additions & 1 deletion hellbender/Views/Main/Settings/WalletInfoView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -200,14 +201,37 @@ 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)
}
.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))
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -460,6 +492,7 @@ struct WalletInfoView: View {
wallet.electrumHost = ""
wallet.electrumPort = 0
wallet.electrumSSL = 0
wallet.electrumAllowInsecureSSL = false
electrumHostText = ""
electrumPortText = ""
connectionTestResult = nil
Expand Down
42 changes: 41 additions & 1 deletion hellbender/Views/Setup/ElectrumServerSetupSection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
Expand All @@ -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))
Expand All @@ -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.")
}
}
}

Expand Down