From 737464e528bc5303c9bbd2409719d8a8869059d2 Mon Sep 17 00:00:00 2001 From: mstrofnone Date: Sun, 3 May 2026 17:23:53 +1000 Subject: [PATCH] feat(electrumx): add relay.testls.bit endpoints (clearnet TLS + Tor) Adds the relay.testls.bit ElectrumX-NMC deployment as a second public Namecoin name resolver. The same box also runs the Namecoin-anchored Nostr relay at wss://relay.testls.bit/, so a single TLSA record on d/testls anchors the trust chain for both services. Default server set (clearnet): + relay.testls.bit:50002 (TLS, self-signed cert pinned) Tor server set (onion-first): + 6cbn4rsk...onion:50001 (plaintext over Tor; re-uses the relay's existing v3 hidden service, onion key already authenticates) + relay.testls.bit:50002 (clearnet TLS fallback) Cert pin (SHA-256 of DER): bb0b35e64235a794e157b69acd72da4ccc16a4d81d0ff6b1d8f7fdfc6cca6cba The new self-signed cert is appended to PINNED_ELECTRUMX_CERTS so strict-TLS Android devices (Samsung One UI 7, GrapheneOS) accept it without a trust-all fallback. Reference deployment also exposes wss://relay.testls.bit/electrumx (WebSocket transport for browser-based Nostr clients), which inherits the relay's existing TLSA-pinned ECDSA cert from d/testls. The current JVM ElectrumXClient is TCP+TLS only; adding a WS variant of the client is a larger change and tracked separately. --- .../namecoin/ElectrumXServer.kt | 16 ++++++++++++ .../namecoin/ElectrumXClient.kt | 25 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/ElectrumXServer.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/ElectrumXServer.kt index 4c6c969379..78416ff983 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/ElectrumXServer.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/ElectrumXServer.kt @@ -99,6 +99,12 @@ val DEFAULT_ELECTRUMX_SERVERS = ElectrumxServer("electrumx.testls.space", 50002, useSsl = true, usePinnedTrustStore = true), ElectrumxServer("nmc2.bitcoins.sk", 57002, useSsl = true, usePinnedTrustStore = true), ElectrumxServer("46.229.238.187", 57002, useSsl = true, usePinnedTrustStore = true), + // relay.testls.bit — second public Namecoin ElectrumX deployment, served + // alongside the Namecoin-anchored Nostr relay at wss://relay.testls.bit/. + // TLS endpoint pinned to a self-signed cert (see PINNED_ELECTRUMX_CERTS). + // Also exposed as wss://relay.testls.bit/electrumx (browser-viable, future + // WS transport — see N1 §"Browser / WebSocket transport" in mstrofnone/nips). + ElectrumxServer("relay.testls.bit", 50002, useSsl = true, usePinnedTrustStore = true), ) /** Tor-preferred server list: onion primary, clearnet fallback. */ @@ -110,6 +116,16 @@ val TOR_ELECTRUMX_SERVERS = useSsl = true, usePinnedTrustStore = true, ), + // relay.testls.bit — hidden service shared with the Nostr relay's onion. + // Plaintext over Tor (port 50001) since the onion key already authenticates + // the endpoint; TLS-on-Tor would only add round-trips with no security gain. + ElectrumxServer( + "6cbn4rskfdr647otej7gpqlmpqcmj723vg2eoeuu7ljbwu6cpdebozyd.onion", + 50001, + useSsl = false, + usePinnedTrustStore = false, + ), ElectrumxServer("electrumx.testls.space", 50002, useSsl = true, usePinnedTrustStore = true), ElectrumxServer("nmc2.bitcoins.sk", 57002, useSsl = true, usePinnedTrustStore = true), + ElectrumxServer("relay.testls.bit", 50002, useSsl = true, usePinnedTrustStore = true), ) diff --git a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/ElectrumXClient.kt b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/ElectrumXClient.kt index f8e0e3152c..a48604a482 100644 --- a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/ElectrumXClient.kt +++ b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/ElectrumXClient.kt @@ -888,6 +888,31 @@ QXYftBo0HbtfsaJjImQdDjmlmRPSzE/RW6iUe+1cesKBC7e8nVf69Yu/fxO4m083 VWwAstlWJfk1GyU7jzVc8svealg/oIiDoOMe6CFSLx1BDv2FeHSpRdqd3fn+AC73 bK2N2smrHUOQnFijuiFw3WOrjERi0eMhjVNfVu9W9ZYa/Wd6SdIzV55LbG+NpmSf 5W7ix41hRvdT6cTAJA== +-----END CERTIFICATE----- + """.trimIndent(), + // relay.testls.bit:50002 — expires 2036-04-30 + // Self-signed RSA-2048 cert (CN=relay.testls.bit) served by + // ElectrumX-NMC alongside the Namecoin-anchored Nostr relay. + // SHA-256 (DER): BB:0B:35:E6:42:35:A7:94:E1:57:B6:9A:CD:72:DA:4C:CC:16:A4:D8:1D:0F:F6:B1:D8:F7:FD:FC:6C:CA:6C:BA + """ +-----BEGIN CERTIFICATE----- +MIIDFzCCAf+gAwIBAgIUAz+Ky5Lu2u1QchHKTwQIStWD8fQwDQYJKoZIhvcNAQEL +BQAwGzEZMBcGA1UEAwwQcmVsYXkudGVzdGxzLmJpdDAeFw0yNjA1MDMwNjEyNDBa +Fw0zNjA0MzAwNjEyNDBaMBsxGTAXBgNVBAMMEHJlbGF5LnRlc3Rscy5iaXQwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCngMim0wilCdclMyIIBRAeFBjE +HWA0l5n3ebCtyepYmyXUrbth2TDdyMHiUNVvE3f7RSAUFtE+Tjb9+xzmLf04qlbC +i3b2DV3xdVOZpRCI4kybmraYG6lRLQJ5I/N8NWgPsFgcy2mZF3q0yMVEkzGAKqUT +QGZd2eBs/OVicbCWKmgyhXlnqGeHIs4iKOqenHKSZ8QE5bhAKaMn+Q116QEdBg12 +svGNoSZSlX8hDNUf5N5pOcsK8vj0Yb0ypJOd0J5eVpYS/KA0oMMwALnEs0H17hfO +IIaWqrbfaqmdR67uzUfci2EoiwQJrXSy7WkNiVX0ikN02VlUPCb2OaSABmwjAgMB +AAGjUzBRMB0GA1UdDgQWBBSgnHYFU93wufP131xk5w843VWhATAfBgNVHSMEGDAW +gBSgnHYFU93wufP131xk5w843VWhATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 +DQEBCwUAA4IBAQAiVC5RJj/Y3S5uNYraPmRLQrgPui9eGlWDh6LeZvjftACA3WiN +XabJtTmHxOFFwxmBtzGVCWKR6udETHyfqaq0me/XoYLjGstYTd14GfoV9Klx7Glh +gLOgqC3Do04o2xnXxhPh00c0jUggKdI05KLVAc4dLfU/XDrOfxBl4XHZY4lYz4CF +bn+n5Q1cqqcGqoJIHl2cgDdrxSMigIpsunjk8cJXO+hsteA/Pd1UUY5plvE9nbNv +hy4QgfNqjy36b0Nbm7Fc9Te9W6zgXjHM+q7KhuQvTfKh2sHbCJzRcy7Chgwqyrfq +NsK0JcBkyRPB+fXmEoE/Xmj/UnOD0fZCCanD -----END CERTIFICATE----- """.trimIndent(), )