mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2025-01-27 10:51:09 +00:00
enable electrum rpc batching on mempool-electrs servers
This commit is contained in:
parent
218c2720e0
commit
fdbcea1625
5 changed files with 75 additions and 19 deletions
|
@ -25,13 +25,11 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
||||||
static final int RETRY_DELAY_SECS = 1;
|
static final int RETRY_DELAY_SECS = 1;
|
||||||
|
|
||||||
private final AtomicLong idCounter;
|
private final AtomicLong idCounter;
|
||||||
|
private final int maxTargetBlocks;
|
||||||
|
|
||||||
public BatchedElectrumServerRpc() {
|
public BatchedElectrumServerRpc(long idCounterValue, int maxTargetBlocks) {
|
||||||
this.idCounter = new AtomicLong();
|
|
||||||
}
|
|
||||||
|
|
||||||
public BatchedElectrumServerRpc(long idCounterValue) {
|
|
||||||
this.idCounter = new AtomicLong(idCounterValue);
|
this.idCounter = new AtomicLong(idCounterValue);
|
||||||
|
this.maxTargetBlocks = maxTargetBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -222,11 +220,19 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
||||||
public Map<Integer, Double> getFeeEstimates(Transport transport, List<Integer> targetBlocks) {
|
public Map<Integer, Double> getFeeEstimates(Transport transport, List<Integer> targetBlocks) {
|
||||||
PagedBatchRequestBuilder<Integer, Double> batchRequest = PagedBatchRequestBuilder.create(transport, idCounter).keysType(Integer.class).returnType(Double.class);
|
PagedBatchRequestBuilder<Integer, Double> batchRequest = PagedBatchRequestBuilder.create(transport, idCounter).keysType(Integer.class).returnType(Double.class);
|
||||||
for(Integer targetBlock : targetBlocks) {
|
for(Integer targetBlock : targetBlocks) {
|
||||||
batchRequest.add(targetBlock, "blockchain.estimatefee", targetBlock);
|
if(targetBlock <= maxTargetBlocks) {
|
||||||
|
batchRequest.add(targetBlock, "blockchain.estimatefee", targetBlock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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) {
|
} catch(JsonRpcBatchException e) {
|
||||||
throw new ElectrumServerRpcException("Error getting fee estimates from connected server: " + e.getErrors(), e);
|
throw new ElectrumServerRpcException("Error getting fee estimates from connected server: " + e.getErrors(), e);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
|
|
|
@ -47,6 +47,8 @@ public class ElectrumServer {
|
||||||
|
|
||||||
private static final Version FULCRUM_MIN_BATCHING_VERSION = new Version("1.6.0");
|
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";
|
public static final String CORE_ELECTRUM_HOST = "127.0.0.1";
|
||||||
|
|
||||||
private static final int MINIMUM_BROADCASTS = 2;
|
private static final int MINIMUM_BROADCASTS = 2;
|
||||||
|
@ -1021,15 +1023,15 @@ public class ElectrumServer {
|
||||||
existingStatuses.add(status);
|
existingStatuses.add(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean supportsBatching(List<String> serverVersion) {
|
public static ServerCapability getServerCapability(List<String> serverVersion) {
|
||||||
if(serverVersion.size() > 0) {
|
if(!serverVersion.isEmpty()) {
|
||||||
String server = serverVersion.get(0).toLowerCase(Locale.ROOT);
|
String server = serverVersion.getFirst().toLowerCase(Locale.ROOT);
|
||||||
if(server.contains("electrumx")) {
|
if(server.contains("electrumx")) {
|
||||||
return true;
|
return new ServerCapability(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(server.startsWith("cormorant")) {
|
if(server.startsWith("cormorant")) {
|
||||||
return true;
|
return new ServerCapability(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(server.startsWith("electrs/")) {
|
if(server.startsWith("electrs/")) {
|
||||||
|
@ -1041,7 +1043,7 @@ public class ElectrumServer {
|
||||||
try {
|
try {
|
||||||
Version version = new Version(electrsVersion);
|
Version version = new Version(electrsVersion);
|
||||||
if(version.compareTo(ELECTRS_MIN_BATCHING_VERSION) >= 0) {
|
if(version.compareTo(ELECTRS_MIN_BATCHING_VERSION) >= 0) {
|
||||||
return true;
|
return new ServerCapability(true);
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
//ignore
|
//ignore
|
||||||
|
@ -1057,7 +1059,26 @@ public class ElectrumServer {
|
||||||
try {
|
try {
|
||||||
Version version = new Version(fulcrumVersion);
|
Version version = new Version(fulcrumVersion);
|
||||||
if(version.compareTo(FULCRUM_MIN_BATCHING_VERSION) >= 0) {
|
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) {
|
} catch(Exception e) {
|
||||||
//ignore
|
//ignore
|
||||||
|
@ -1065,7 +1086,7 @@ public class ElectrumServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return new ServerCapability(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ServerVersionService extends Service<List<String>> {
|
public static class ServerVersionService extends Service<List<String>> {
|
||||||
|
@ -1196,9 +1217,10 @@ public class ElectrumServer {
|
||||||
firstCall = false;
|
firstCall = false;
|
||||||
|
|
||||||
//If electrumx is detected, we can upgrade to batched RPC. Electrs/EPS do not support batching.
|
//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");
|
log.debug("Upgrading to batched JSON-RPC");
|
||||||
electrumServerRpc = new BatchedElectrumServerRpc(electrumServerRpc.getIdCounterValue());
|
electrumServerRpc = new BatchedElectrumServerRpc(electrumServerRpc.getIdCounterValue(), serverCapability.getMaxTargetBlocks());
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockHeaderTip tip;
|
BlockHeaderTip tip;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -603,7 +603,8 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
testConnection.setGraphic(getGlyph(FontAwesome5.Glyph.CHECK_CIRCLE, "success"));
|
testConnection.setGraphic(getGlyph(FontAwesome5.Glyph.CHECK_CIRCLE, "success"));
|
||||||
if(serverVersion != null) {
|
if(serverVersion != null) {
|
||||||
testResults.setText("Connected to " + serverVersion.get(0) + " on protocol version " + serverVersion.get(1));
|
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.");
|
testResults.setText(testResults.getText() + "\nBatched RPC enabled.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,7 +168,8 @@ public class ServerTestDialog extends DialogWindow {
|
||||||
testStatus.setText("Success");
|
testStatus.setText("Success");
|
||||||
if(serverVersion != null) {
|
if(serverVersion != null) {
|
||||||
testResults.setText("Connected to " + serverVersion.get(0) + " on protocol version " + serverVersion.get(1));
|
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.");
|
testResults.setText(testResults.getText() + "\nBatched RPC enabled.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue