From 38f0068411e37adc1cbdeae563d57064e01256ac Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Tue, 3 Jun 2025 12:38:03 +0200 Subject: [PATCH] detect if electrum server supports scripthash unsubscribe capability --- .../sparrow/net/ElectrumServer.java | 18 ++++++++++-------- .../sparrow/net/ServerCapability.java | 19 +++++++++++++------ 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServer.java b/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServer.java index 033fece2..75baf3a3 100644 --- a/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServer.java +++ b/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServer.java @@ -1255,11 +1255,11 @@ public class ElectrumServer { if(!serverVersion.isEmpty()) { String server = serverVersion.getFirst().toLowerCase(Locale.ROOT); if(server.contains("electrumx")) { - return new ServerCapability(true); + return new ServerCapability(true, false); } if(server.startsWith("cormorant")) { - return new ServerCapability(true, false, true); + return new ServerCapability(true, false, true, false); } if(server.startsWith("electrs/")) { @@ -1271,7 +1271,7 @@ public class ElectrumServer { try { Version version = new Version(electrsVersion); if(version.compareTo(ELECTRS_MIN_BATCHING_VERSION) >= 0) { - return new ServerCapability(true); + return new ServerCapability(true, true); } } catch(Exception e) { //ignore @@ -1287,7 +1287,7 @@ public class ElectrumServer { try { Version version = new Version(fulcrumVersion); if(version.compareTo(FULCRUM_MIN_BATCHING_VERSION) >= 0) { - return new ServerCapability(true); + return new ServerCapability(true, true); } } catch(Exception e) { //ignore @@ -1306,7 +1306,7 @@ public class ElectrumServer { Version version = new Version(mempoolElectrsVersion); if(version.compareTo(MEMPOOL_ELECTRS_MIN_BATCHING_VERSION) > 0 || (version.compareTo(MEMPOOL_ELECTRS_MIN_BATCHING_VERSION) == 0 && (!mempoolElectrsSuffix.contains("dev") || mempoolElectrsSuffix.contains("dev-249848d")))) { - return new ServerCapability(true, 25); + return new ServerCapability(true, 25, false); } } catch(Exception e) { //ignore @@ -1314,7 +1314,7 @@ public class ElectrumServer { } } - return new ServerCapability(false); + return new ServerCapability(false, true); } public static class ServerVersionService extends Service> { @@ -2051,7 +2051,9 @@ public class ElectrumServer { private void subscribeRecent(ElectrumServer electrumServer) { Set unsubscribeScriptHashes = new HashSet<>(subscribedRecent); unsubscribeScriptHashes.removeIf(subscribedScriptHashes::containsKey); - electrumServerRpc.unsubscribeScriptHashes(transport, unsubscribeScriptHashes); + if(!unsubscribeScriptHashes.isEmpty() && serverCapability.supportsUnsubscribe()) { + electrumServerRpc.unsubscribeScriptHashes(transport, unsubscribeScriptHashes); + } subscribedRecent.removeAll(unsubscribeScriptHashes); broadcastRecent.clear(); @@ -2072,7 +2074,7 @@ public class ElectrumServer { if(!subscribeScriptHashes.isEmpty()) { Random random = new Random(); - int additionalRandomScriptHashes = random.nextInt(8) + 4; + int additionalRandomScriptHashes = random.nextInt(4) + 4; for(int i = 0; i < additionalRandomScriptHashes; i++) { byte[] randomScriptHashBytes = new byte[32]; random.nextBytes(randomScriptHashBytes); diff --git a/src/main/java/com/sparrowwallet/sparrow/net/ServerCapability.java b/src/main/java/com/sparrowwallet/sparrow/net/ServerCapability.java index 98c7099b..fb15e240 100644 --- a/src/main/java/com/sparrowwallet/sparrow/net/ServerCapability.java +++ b/src/main/java/com/sparrowwallet/sparrow/net/ServerCapability.java @@ -7,27 +7,30 @@ public class ServerCapability { private final int maxTargetBlocks; private final boolean supportsRecentMempool; private final boolean supportsBlockStats; + private final boolean supportsUnsubscribe; - public ServerCapability(boolean supportsBatching) { - this(supportsBatching, AppServices.TARGET_BLOCKS_RANGE.getLast()); + public ServerCapability(boolean supportsBatching, boolean supportsUnsubscribe) { + this(supportsBatching, AppServices.TARGET_BLOCKS_RANGE.getLast(), supportsUnsubscribe); } - public ServerCapability(boolean supportsBatching, int maxTargetBlocks) { + public ServerCapability(boolean supportsBatching, int maxTargetBlocks, boolean supportsUnsubscribe) { this.supportsBatching = supportsBatching; this.maxTargetBlocks = maxTargetBlocks; this.supportsRecentMempool = false; this.supportsBlockStats = false; + this.supportsUnsubscribe = supportsUnsubscribe; } - public ServerCapability(boolean supportsBatching, boolean supportsRecentMempool, boolean supportsBlockStats) { - this(supportsBatching, AppServices.TARGET_BLOCKS_RANGE.getLast(), supportsRecentMempool, supportsBlockStats); + public ServerCapability(boolean supportsBatching, boolean supportsRecentMempool, boolean supportsBlockStats, boolean supportsUnsubscribe) { + this(supportsBatching, AppServices.TARGET_BLOCKS_RANGE.getLast(), supportsRecentMempool, supportsBlockStats, supportsUnsubscribe); } - public ServerCapability(boolean supportsBatching, int maxTargetBlocks, boolean supportsRecentMempool, boolean supportsBlockStats) { + public ServerCapability(boolean supportsBatching, int maxTargetBlocks, boolean supportsRecentMempool, boolean supportsBlockStats, boolean supportsUnsubscribe) { this.supportsBatching = supportsBatching; this.maxTargetBlocks = maxTargetBlocks; this.supportsRecentMempool = supportsRecentMempool; this.supportsBlockStats = supportsBlockStats; + this.supportsUnsubscribe = supportsUnsubscribe; } public boolean supportsBatching() { @@ -45,4 +48,8 @@ public class ServerCapability { public boolean supportsBlockStats() { return supportsBlockStats; } + + public boolean supportsUnsubscribe() { + return supportsUnsubscribe; + } }