enable electrum rpc batching on mempool-electrs servers

This commit is contained in:
Craig Raw 2025-01-15 09:09:25 +02:00
parent 218c2720e0
commit fdbcea1625
5 changed files with 75 additions and 19 deletions

View file

@ -25,13 +25,11 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
static final int RETRY_DELAY_SECS = 1;
private final AtomicLong idCounter;
private final int maxTargetBlocks;
public BatchedElectrumServerRpc() {
this.idCounter = new AtomicLong();
}
public BatchedElectrumServerRpc(long idCounterValue) {
public BatchedElectrumServerRpc(long idCounterValue, int maxTargetBlocks) {
this.idCounter = new AtomicLong(idCounterValue);
this.maxTargetBlocks = maxTargetBlocks;
}
@Override
@ -222,11 +220,19 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
public Map<Integer, Double> getFeeEstimates(Transport transport, List<Integer> targetBlocks) {
PagedBatchRequestBuilder<Integer, Double> batchRequest = PagedBatchRequestBuilder.create(transport, idCounter).keysType(Integer.class).returnType(Double.class);
for(Integer targetBlock : targetBlocks) {
batchRequest.add(targetBlock, "blockchain.estimatefee", targetBlock);
if(targetBlock <= maxTargetBlocks) {
batchRequest.add(targetBlock, "blockchain.estimatefee", targetBlock);
}
}
try {
return batchRequest.execute();
Map<Integer, Double> result = batchRequest.execute();
for(Integer targetBlock : targetBlocks) {
if(targetBlock > maxTargetBlocks) {
result.put(targetBlock, result.values().stream().mapToDouble(v -> v).min().orElse(0.0001d));
}
}
return result;
} catch(JsonRpcBatchException e) {
throw new ElectrumServerRpcException("Error getting fee estimates from connected server: " + e.getErrors(), e);
} catch(Exception e) {

View file

@ -47,6 +47,8 @@ public class ElectrumServer {
private static final Version FULCRUM_MIN_BATCHING_VERSION = new Version("1.6.0");
private static final Version MEMPOOL_ELECTRS_MIN_BATCHING_VERSION = new Version("3.1.0");
public static final String CORE_ELECTRUM_HOST = "127.0.0.1";
private static final int MINIMUM_BROADCASTS = 2;
@ -1021,15 +1023,15 @@ public class ElectrumServer {
existingStatuses.add(status);
}
public static boolean supportsBatching(List<String> serverVersion) {
if(serverVersion.size() > 0) {
String server = serverVersion.get(0).toLowerCase(Locale.ROOT);
public static ServerCapability getServerCapability(List<String> serverVersion) {
if(!serverVersion.isEmpty()) {
String server = serverVersion.getFirst().toLowerCase(Locale.ROOT);
if(server.contains("electrumx")) {
return true;
return new ServerCapability(true);
}
if(server.startsWith("cormorant")) {
return true;
return new ServerCapability(true);
}
if(server.startsWith("electrs/")) {
@ -1041,7 +1043,7 @@ public class ElectrumServer {
try {
Version version = new Version(electrsVersion);
if(version.compareTo(ELECTRS_MIN_BATCHING_VERSION) >= 0) {
return true;
return new ServerCapability(true);
}
} catch(Exception e) {
//ignore
@ -1057,7 +1059,26 @@ public class ElectrumServer {
try {
Version version = new Version(fulcrumVersion);
if(version.compareTo(FULCRUM_MIN_BATCHING_VERSION) >= 0) {
return true;
return new ServerCapability(true);
}
} catch(Exception e) {
//ignore
}
}
if(server.startsWith("mempool-electrs")) {
String mempoolElectrsVersion = server.substring("mempool-electrs".length()).trim();
int dashIndex = mempoolElectrsVersion.indexOf('-');
String mempoolElectrsSuffix = "";
if(dashIndex > -1) {
mempoolElectrsSuffix = mempoolElectrsVersion.substring(dashIndex);
mempoolElectrsVersion = mempoolElectrsVersion.substring(0, dashIndex);
}
try {
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);
}
} catch(Exception e) {
//ignore
@ -1065,7 +1086,7 @@ public class ElectrumServer {
}
}
return false;
return new ServerCapability(false);
}
public static class ServerVersionService extends Service<List<String>> {
@ -1196,9 +1217,10 @@ public class ElectrumServer {
firstCall = false;
//If electrumx is detected, we can upgrade to batched RPC. Electrs/EPS do not support batching.
if(supportsBatching(serverVersion)) {
ServerCapability serverCapability = getServerCapability(serverVersion);
if(serverCapability.supportsBatching()) {
log.debug("Upgrading to batched JSON-RPC");
electrumServerRpc = new BatchedElectrumServerRpc(electrumServerRpc.getIdCounterValue());
electrumServerRpc = new BatchedElectrumServerRpc(electrumServerRpc.getIdCounterValue(), serverCapability.getMaxTargetBlocks());
}
BlockHeaderTip tip;

View file

@ -0,0 +1,26 @@
package com.sparrowwallet.sparrow.net;
import com.sparrowwallet.sparrow.AppServices;
public class ServerCapability {
private final boolean supportsBatching;
private final int maxTargetBlocks;
public ServerCapability(boolean supportsBatching) {
this.supportsBatching = supportsBatching;
this.maxTargetBlocks = AppServices.TARGET_BLOCKS_RANGE.getLast();
}
public ServerCapability(boolean supportsBatching, int maxTargetBlocks) {
this.supportsBatching = supportsBatching;
this.maxTargetBlocks = maxTargetBlocks;
}
public boolean supportsBatching() {
return supportsBatching;
}
public int getMaxTargetBlocks() {
return maxTargetBlocks;
}
}

View file

@ -603,7 +603,8 @@ public class ServerPreferencesController extends PreferencesDetailController {
testConnection.setGraphic(getGlyph(FontAwesome5.Glyph.CHECK_CIRCLE, "success"));
if(serverVersion != null) {
testResults.setText("Connected to " + serverVersion.get(0) + " on protocol version " + serverVersion.get(1));
if(ElectrumServer.supportsBatching(serverVersion)) {
ServerCapability serverCapability = ElectrumServer.getServerCapability(serverVersion);
if(serverCapability.supportsBatching()) {
testResults.setText(testResults.getText() + "\nBatched RPC enabled.");
}
}

View file

@ -168,7 +168,8 @@ public class ServerTestDialog extends DialogWindow {
testStatus.setText("Success");
if(serverVersion != null) {
testResults.setText("Connected to " + serverVersion.get(0) + " on protocol version " + serverVersion.get(1));
if(ElectrumServer.supportsBatching(serverVersion)) {
ServerCapability serverCapability = ElectrumServer.getServerCapability(serverVersion);
if(serverCapability.supportsBatching()) {
testResults.setText(testResults.getText() + "\nBatched RPC enabled.");
}
}