forked from Qortal/qortal
Extracted Server classes into ServerConfigurationInfo in order offer foreign blockchain server information to the Core API
This commit is contained in:
parent
deaef4fc4a
commit
de9c3e551d
@ -19,6 +19,7 @@ import org.qortal.crosschain.AddressInfo;
|
|||||||
import org.qortal.crosschain.Bitcoin;
|
import org.qortal.crosschain.Bitcoin;
|
||||||
import org.qortal.crosschain.ForeignBlockchainException;
|
import org.qortal.crosschain.ForeignBlockchainException;
|
||||||
import org.qortal.crosschain.SimpleTransaction;
|
import org.qortal.crosschain.SimpleTransaction;
|
||||||
|
import org.qortal.crosschain.ServerConfigurationInfo;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
@ -283,4 +284,24 @@ public class CrossChainBitcoinResource {
|
|||||||
return spendTransaction.getTxId().toString();
|
return spendTransaction.getTxId().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/serverinfos")
|
||||||
|
@Operation(
|
||||||
|
summary = "Returns current Bitcoin server configuration",
|
||||||
|
description = "Returns current Bitcoin server locations and use status",
|
||||||
|
responses = {
|
||||||
|
@ApiResponse(
|
||||||
|
content = @Content(
|
||||||
|
mediaType = MediaType.APPLICATION_JSON,
|
||||||
|
schema = @Schema(
|
||||||
|
implementation = ServerConfigurationInfo.class
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public ServerConfigurationInfo getServerConfiguration() {
|
||||||
|
|
||||||
|
return CrossChainUtils.buildServerConfigurationInfo(Bitcoin.getInstance());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import org.qortal.crosschain.AddressInfo;
|
|||||||
import org.qortal.crosschain.Digibyte;
|
import org.qortal.crosschain.Digibyte;
|
||||||
import org.qortal.crosschain.ForeignBlockchainException;
|
import org.qortal.crosschain.ForeignBlockchainException;
|
||||||
import org.qortal.crosschain.SimpleTransaction;
|
import org.qortal.crosschain.SimpleTransaction;
|
||||||
|
import org.qortal.crosschain.ServerConfigurationInfo;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
@ -283,4 +284,24 @@ public class CrossChainDigibyteResource {
|
|||||||
return spendTransaction.getTxId().toString();
|
return spendTransaction.getTxId().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/serverinfos")
|
||||||
|
@Operation(
|
||||||
|
summary = "Returns current Digibyte server configuration",
|
||||||
|
description = "Returns current Digibyte server locations and use status",
|
||||||
|
responses = {
|
||||||
|
@ApiResponse(
|
||||||
|
content = @Content(
|
||||||
|
mediaType = MediaType.APPLICATION_JSON,
|
||||||
|
schema = @Schema(
|
||||||
|
implementation = ServerConfigurationInfo.class
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public ServerConfigurationInfo getServerConfiguration() {
|
||||||
|
|
||||||
|
return CrossChainUtils.buildServerConfigurationInfo(Digibyte.getInstance());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import org.qortal.crosschain.AddressInfo;
|
|||||||
import org.qortal.crosschain.Dogecoin;
|
import org.qortal.crosschain.Dogecoin;
|
||||||
import org.qortal.crosschain.ForeignBlockchainException;
|
import org.qortal.crosschain.ForeignBlockchainException;
|
||||||
import org.qortal.crosschain.SimpleTransaction;
|
import org.qortal.crosschain.SimpleTransaction;
|
||||||
|
import org.qortal.crosschain.ServerConfigurationInfo;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
@ -283,4 +284,24 @@ public class CrossChainDogecoinResource {
|
|||||||
return spendTransaction.getTxId().toString();
|
return spendTransaction.getTxId().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/serverinfos")
|
||||||
|
@Operation(
|
||||||
|
summary = "Returns current Dogecoin server configuration",
|
||||||
|
description = "Returns current Dogecoin server locations and use status",
|
||||||
|
responses = {
|
||||||
|
@ApiResponse(
|
||||||
|
content = @Content(
|
||||||
|
mediaType = MediaType.APPLICATION_JSON,
|
||||||
|
schema = @Schema(
|
||||||
|
implementation = ServerConfigurationInfo.class
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public ServerConfigurationInfo getServerConfiguration() {
|
||||||
|
|
||||||
|
return CrossChainUtils.buildServerConfigurationInfo(Dogecoin.getInstance());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import org.qortal.crosschain.AddressInfo;
|
|||||||
import org.qortal.crosschain.ForeignBlockchainException;
|
import org.qortal.crosschain.ForeignBlockchainException;
|
||||||
import org.qortal.crosschain.Litecoin;
|
import org.qortal.crosschain.Litecoin;
|
||||||
import org.qortal.crosschain.SimpleTransaction;
|
import org.qortal.crosschain.SimpleTransaction;
|
||||||
|
import org.qortal.crosschain.ServerConfigurationInfo;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
@ -283,4 +284,24 @@ public class CrossChainLitecoinResource {
|
|||||||
return spendTransaction.getTxId().toString();
|
return spendTransaction.getTxId().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/serverinfos")
|
||||||
|
@Operation(
|
||||||
|
summary = "Returns current Litecoin server configuration",
|
||||||
|
description = "Returns current Litecoin server locations and use status",
|
||||||
|
responses = {
|
||||||
|
@ApiResponse(
|
||||||
|
content = @Content(
|
||||||
|
mediaType = MediaType.APPLICATION_JSON,
|
||||||
|
schema = @Schema(
|
||||||
|
implementation = ServerConfigurationInfo.class
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public ServerConfigurationInfo getServerConfiguration() {
|
||||||
|
|
||||||
|
return CrossChainUtils.buildServerConfigurationInfo(Litecoin.getInstance());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import org.qortal.api.model.crosschain.PirateChainSendRequest;
|
|||||||
import org.qortal.crosschain.ForeignBlockchainException;
|
import org.qortal.crosschain.ForeignBlockchainException;
|
||||||
import org.qortal.crosschain.PirateChain;
|
import org.qortal.crosschain.PirateChain;
|
||||||
import org.qortal.crosschain.SimpleTransaction;
|
import org.qortal.crosschain.SimpleTransaction;
|
||||||
|
import org.qortal.crosschain.ServerConfigurationInfo;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
@ -329,4 +330,25 @@ public class CrossChainPirateChainResource {
|
|||||||
throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.FOREIGN_BLOCKCHAIN_NETWORK_ISSUE, e.getMessage());
|
throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.FOREIGN_BLOCKCHAIN_NETWORK_ISSUE, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/serverinfos")
|
||||||
|
@Operation(
|
||||||
|
summary = "Returns current PirateChain server configuration",
|
||||||
|
description = "Returns current PirateChain server locations and use status",
|
||||||
|
responses = {
|
||||||
|
@ApiResponse(
|
||||||
|
content = @Content(
|
||||||
|
mediaType = MediaType.APPLICATION_JSON,
|
||||||
|
schema = @Schema(
|
||||||
|
implementation = ServerConfigurationInfo.class
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public ServerConfigurationInfo getServerConfiguration() {
|
||||||
|
|
||||||
|
return CrossChainUtils.buildServerConfigurationInfo(PirateChain.getInstance());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import org.qortal.crosschain.AddressInfo;
|
|||||||
import org.qortal.crosschain.ForeignBlockchainException;
|
import org.qortal.crosschain.ForeignBlockchainException;
|
||||||
import org.qortal.crosschain.Ravencoin;
|
import org.qortal.crosschain.Ravencoin;
|
||||||
import org.qortal.crosschain.SimpleTransaction;
|
import org.qortal.crosschain.SimpleTransaction;
|
||||||
|
import org.qortal.crosschain.ServerConfigurationInfo;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
@ -283,4 +284,24 @@ public class CrossChainRavencoinResource {
|
|||||||
return spendTransaction.getTxId().toString();
|
return spendTransaction.getTxId().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/serverinfos")
|
||||||
|
@Operation(
|
||||||
|
summary = "Returns current Ravencoin server configuration",
|
||||||
|
description = "Returns current Ravencoin server locations and use status",
|
||||||
|
responses = {
|
||||||
|
@ApiResponse(
|
||||||
|
content = @Content(
|
||||||
|
mediaType = MediaType.APPLICATION_JSON,
|
||||||
|
schema = @Schema(
|
||||||
|
implementation = ServerConfigurationInfo.class
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public ServerConfigurationInfo getServerConfiguration() {
|
||||||
|
|
||||||
|
return CrossChainUtils.buildServerConfigurationInfo(Ravencoin.getInstance());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import org.bitcoinj.params.MainNetParams;
|
|||||||
import org.bitcoinj.params.RegTestParams;
|
import org.bitcoinj.params.RegTestParams;
|
||||||
import org.bitcoinj.params.TestNet3Params;
|
import org.bitcoinj.params.TestNet3Params;
|
||||||
import org.qortal.crosschain.ElectrumX.Server;
|
import org.qortal.crosschain.ElectrumX.Server;
|
||||||
import org.qortal.crosschain.ElectrumX.Server.ConnectionType;
|
import org.qortal.crosschain.ChainableServer.ConnectionType;
|
||||||
import org.qortal.settings.Settings;
|
import org.qortal.settings.Settings;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -3,6 +3,7 @@ package org.qortal.crosschain;
|
|||||||
import cash.z.wallet.sdk.rpc.CompactFormats.CompactBlock;
|
import cash.z.wallet.sdk.rpc.CompactFormats.CompactBlock;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public abstract class BitcoinyBlockchainProvider {
|
public abstract class BitcoinyBlockchainProvider {
|
||||||
|
|
||||||
@ -59,4 +60,11 @@ public abstract class BitcoinyBlockchainProvider {
|
|||||||
/** Broadcasts raw, serialized, transaction bytes to network, returning success/failure. */
|
/** Broadcasts raw, serialized, transaction bytes to network, returning success/failure. */
|
||||||
public abstract void broadcastTransaction(byte[] rawTransaction) throws ForeignBlockchainException;
|
public abstract void broadcastTransaction(byte[] rawTransaction) throws ForeignBlockchainException;
|
||||||
|
|
||||||
|
public abstract Set<ChainableServer> getServers();
|
||||||
|
|
||||||
|
public abstract List<ChainableServer> getRemainingServers();
|
||||||
|
|
||||||
|
public abstract Set<ChainableServer> getUselessServers();
|
||||||
|
|
||||||
|
public abstract ChainableServer getCurrentServer();
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import org.bitcoinj.params.RegTestParams;
|
|||||||
import org.bitcoinj.params.TestNet3Params;
|
import org.bitcoinj.params.TestNet3Params;
|
||||||
import org.libdohj.params.DigibyteMainNetParams;
|
import org.libdohj.params.DigibyteMainNetParams;
|
||||||
import org.qortal.crosschain.ElectrumX.Server;
|
import org.qortal.crosschain.ElectrumX.Server;
|
||||||
import org.qortal.crosschain.ElectrumX.Server.ConnectionType;
|
import org.qortal.crosschain.ChainableServer.ConnectionType;
|
||||||
import org.qortal.settings.Settings;
|
import org.qortal.settings.Settings;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -6,7 +6,7 @@ import org.bitcoinj.core.NetworkParameters;
|
|||||||
import org.libdohj.params.DogecoinMainNetParams;
|
import org.libdohj.params.DogecoinMainNetParams;
|
||||||
import org.libdohj.params.DogecoinTestNet3Params;
|
import org.libdohj.params.DogecoinTestNet3Params;
|
||||||
import org.qortal.crosschain.ElectrumX.Server;
|
import org.qortal.crosschain.ElectrumX.Server;
|
||||||
import org.qortal.crosschain.ElectrumX.Server.ConnectionType;
|
import org.qortal.crosschain.ChainableServer.ConnectionType;
|
||||||
import org.qortal.settings.Settings;
|
import org.qortal.settings.Settings;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -43,12 +43,11 @@ public class ElectrumX extends BitcoinyBlockchainProvider {
|
|||||||
private static final String VERBOSE_TRANSACTIONS_UNSUPPORTED_MESSAGE = "verbose transactions are currently unsupported";
|
private static final String VERBOSE_TRANSACTIONS_UNSUPPORTED_MESSAGE = "verbose transactions are currently unsupported";
|
||||||
|
|
||||||
private static final int RESPONSE_TIME_READINGS = 5;
|
private static final int RESPONSE_TIME_READINGS = 5;
|
||||||
private static final long MAX_AVG_RESPONSE_TIME = 1000L; // ms
|
private static final long MAX_AVG_RESPONSE_TIME = 2000L; // ms
|
||||||
|
|
||||||
public static class Server {
|
public static class Server implements ChainableServer {
|
||||||
String hostname;
|
String hostname;
|
||||||
|
|
||||||
public enum ConnectionType { TCP, SSL }
|
|
||||||
ConnectionType connectionType;
|
ConnectionType connectionType;
|
||||||
|
|
||||||
int port;
|
int port;
|
||||||
@ -60,6 +59,7 @@ public class ElectrumX extends BitcoinyBlockchainProvider {
|
|||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void addResponseTime(long responseTime) {
|
public void addResponseTime(long responseTime) {
|
||||||
while (this.responseTimes.size() > RESPONSE_TIME_READINGS) {
|
while (this.responseTimes.size() > RESPONSE_TIME_READINGS) {
|
||||||
this.responseTimes.remove(0);
|
this.responseTimes.remove(0);
|
||||||
@ -67,6 +67,7 @@ public class ElectrumX extends BitcoinyBlockchainProvider {
|
|||||||
this.responseTimes.add(responseTime);
|
this.responseTimes.add(responseTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public long averageResponseTime() {
|
public long averageResponseTime() {
|
||||||
if (this.responseTimes.size() < RESPONSE_TIME_READINGS) {
|
if (this.responseTimes.size() < RESPONSE_TIME_READINGS) {
|
||||||
// Not enough readings yet
|
// Not enough readings yet
|
||||||
@ -79,6 +80,21 @@ public class ElectrumX extends BitcoinyBlockchainProvider {
|
|||||||
return 0L;
|
return 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHostName() {
|
||||||
|
return this.hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPort() {
|
||||||
|
return this.port;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConnectionType getConnectionType() {
|
||||||
|
return this.connectionType;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
if (other == this)
|
if (other == this)
|
||||||
@ -104,9 +120,9 @@ public class ElectrumX extends BitcoinyBlockchainProvider {
|
|||||||
return String.format("%s:%s:%d", this.connectionType.name(), this.hostname, this.port);
|
return String.format("%s:%s:%d", this.connectionType.name(), this.hostname, this.port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private Set<Server> servers = new HashSet<>();
|
private Set<ChainableServer> servers = new HashSet<>();
|
||||||
private List<Server> remainingServers = new ArrayList<>();
|
private List<ChainableServer> remainingServers = new ArrayList<>();
|
||||||
private Set<Server> uselessServers = Collections.synchronizedSet(new HashSet<>());
|
private Set<ChainableServer> uselessServers = Collections.synchronizedSet(new HashSet<>());
|
||||||
|
|
||||||
private final String netId;
|
private final String netId;
|
||||||
private final String expectedGenesisHash;
|
private final String expectedGenesisHash;
|
||||||
@ -114,7 +130,7 @@ public class ElectrumX extends BitcoinyBlockchainProvider {
|
|||||||
private Bitcoiny blockchain;
|
private Bitcoiny blockchain;
|
||||||
|
|
||||||
private final Object serverLock = new Object();
|
private final Object serverLock = new Object();
|
||||||
private Server currentServer;
|
private ChainableServer currentServer;
|
||||||
private Socket socket;
|
private Socket socket;
|
||||||
private Scanner scanner;
|
private Scanner scanner;
|
||||||
private int nextId = 1;
|
private int nextId = 1;
|
||||||
@ -638,7 +654,7 @@ public class ElectrumX extends BitcoinyBlockchainProvider {
|
|||||||
if (!this.remainingServers.isEmpty()) {
|
if (!this.remainingServers.isEmpty()) {
|
||||||
long averageResponseTime = this.currentServer.averageResponseTime();
|
long averageResponseTime = this.currentServer.averageResponseTime();
|
||||||
if (averageResponseTime > MAX_AVG_RESPONSE_TIME) {
|
if (averageResponseTime > MAX_AVG_RESPONSE_TIME) {
|
||||||
LOGGER.info("Slow average response time {}ms from {} - trying another server...", averageResponseTime, this.currentServer.hostname);
|
LOGGER.info("Slow average response time {}ms from {} - trying another server...", averageResponseTime, this.currentServer.getHostName());
|
||||||
this.closeServer();
|
this.closeServer();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -663,20 +679,20 @@ public class ElectrumX extends BitcoinyBlockchainProvider {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
while (!this.remainingServers.isEmpty()) {
|
while (!this.remainingServers.isEmpty()) {
|
||||||
Server server = this.remainingServers.remove(RANDOM.nextInt(this.remainingServers.size()));
|
ChainableServer server = this.remainingServers.remove(RANDOM.nextInt(this.remainingServers.size()));
|
||||||
LOGGER.trace(() -> String.format("Connecting to %s", server));
|
LOGGER.trace(() -> String.format("Connecting to %s", server));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SocketAddress endpoint = new InetSocketAddress(server.hostname, server.port);
|
SocketAddress endpoint = new InetSocketAddress(server.getHostName(), server.getPort());
|
||||||
int timeout = 5000; // ms
|
int timeout = 5000; // ms
|
||||||
|
|
||||||
this.socket = new Socket();
|
this.socket = new Socket();
|
||||||
this.socket.connect(endpoint, timeout);
|
this.socket.connect(endpoint, timeout);
|
||||||
this.socket.setTcpNoDelay(true);
|
this.socket.setTcpNoDelay(true);
|
||||||
|
|
||||||
if (server.connectionType == Server.ConnectionType.SSL) {
|
if (server.getConnectionType() == Server.ConnectionType.SSL) {
|
||||||
SSLSocketFactory factory = TrustlessSSLSocketFactory.getSocketFactory();
|
SSLSocketFactory factory = TrustlessSSLSocketFactory.getSocketFactory();
|
||||||
this.socket = factory.createSocket(this.socket, server.hostname, server.port, true);
|
this.socket = factory.createSocket(this.socket, server.getHostName(), server.getPort(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.scanner = new Scanner(this.socket.getInputStream());
|
this.scanner = new Scanner(this.socket.getInputStream());
|
||||||
@ -832,7 +848,7 @@ public class ElectrumX extends BitcoinyBlockchainProvider {
|
|||||||
* Closes connection to <tt>server</tt> if it is currently connected server.
|
* Closes connection to <tt>server</tt> if it is currently connected server.
|
||||||
* @param server
|
* @param server
|
||||||
*/
|
*/
|
||||||
private void closeServer(Server server) {
|
private void closeServer(ChainableServer server) {
|
||||||
synchronized (this.serverLock) {
|
synchronized (this.serverLock) {
|
||||||
if (this.currentServer == null || !this.currentServer.equals(server))
|
if (this.currentServer == null || !this.currentServer.equals(server))
|
||||||
return;
|
return;
|
||||||
@ -857,4 +873,24 @@ public class ElectrumX extends BitcoinyBlockchainProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<ChainableServer> getServers() {
|
||||||
|
LOGGER.info("getting servers");
|
||||||
|
return servers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ChainableServer> getRemainingServers() {
|
||||||
|
return remainingServers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<ChainableServer> getUselessServers() {
|
||||||
|
return uselessServers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChainableServer getCurrentServer() {
|
||||||
|
return currentServer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import org.libdohj.params.LitecoinMainNetParams;
|
|||||||
import org.libdohj.params.LitecoinRegTestParams;
|
import org.libdohj.params.LitecoinRegTestParams;
|
||||||
import org.libdohj.params.LitecoinTestNet3Params;
|
import org.libdohj.params.LitecoinTestNet3Params;
|
||||||
import org.qortal.crosschain.ElectrumX.Server;
|
import org.qortal.crosschain.ElectrumX.Server;
|
||||||
import org.qortal.crosschain.ElectrumX.Server.ConnectionType;
|
import org.qortal.crosschain.ChainableServer.ConnectionType;
|
||||||
import org.qortal.settings.Settings;
|
import org.qortal.settings.Settings;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -13,7 +13,7 @@ import org.libdohj.params.PirateChainMainNetParams;
|
|||||||
import org.qortal.api.model.crosschain.PirateChainSendRequest;
|
import org.qortal.api.model.crosschain.PirateChainSendRequest;
|
||||||
import org.qortal.controller.PirateChainWalletController;
|
import org.qortal.controller.PirateChainWalletController;
|
||||||
import org.qortal.crosschain.PirateLightClient.Server;
|
import org.qortal.crosschain.PirateLightClient.Server;
|
||||||
import org.qortal.crosschain.PirateLightClient.Server.ConnectionType;
|
import org.qortal.crosschain.ChainableServer.ConnectionType;
|
||||||
import org.qortal.crypto.Crypto;
|
import org.qortal.crypto.Crypto;
|
||||||
import org.qortal.settings.Settings;
|
import org.qortal.settings.Settings;
|
||||||
import org.qortal.transform.TransformationException;
|
import org.qortal.transform.TransformationException;
|
||||||
|
@ -30,10 +30,9 @@ public class PirateLightClient extends BitcoinyBlockchainProvider {
|
|||||||
private static final int RESPONSE_TIME_READINGS = 5;
|
private static final int RESPONSE_TIME_READINGS = 5;
|
||||||
private static final long MAX_AVG_RESPONSE_TIME = 500L; // ms
|
private static final long MAX_AVG_RESPONSE_TIME = 500L; // ms
|
||||||
|
|
||||||
public static class Server {
|
public static class Server implements ChainableServer{
|
||||||
String hostname;
|
String hostname;
|
||||||
|
|
||||||
public enum ConnectionType { TCP, SSL }
|
|
||||||
ConnectionType connectionType;
|
ConnectionType connectionType;
|
||||||
|
|
||||||
int port;
|
int port;
|
||||||
@ -64,6 +63,21 @@ public class PirateLightClient extends BitcoinyBlockchainProvider {
|
|||||||
return 0L;
|
return 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHostName() {
|
||||||
|
return this.hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPort() {
|
||||||
|
return this.port;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChainableServer.ConnectionType getConnectionType() {
|
||||||
|
return this.connectionType;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
if (other == this)
|
if (other == this)
|
||||||
@ -89,9 +103,9 @@ public class PirateLightClient extends BitcoinyBlockchainProvider {
|
|||||||
return String.format("%s:%s:%d", this.connectionType.name(), this.hostname, this.port);
|
return String.format("%s:%s:%d", this.connectionType.name(), this.hostname, this.port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private Set<Server> servers = new HashSet<>();
|
private Set<ChainableServer> servers = new HashSet<>();
|
||||||
private List<Server> remainingServers = new ArrayList<>();
|
private List<ChainableServer> remainingServers = new ArrayList<>();
|
||||||
private Set<Server> uselessServers = Collections.synchronizedSet(new HashSet<>());
|
private Set<ChainableServer> uselessServers = Collections.synchronizedSet(new HashSet<>());
|
||||||
|
|
||||||
private final String netId;
|
private final String netId;
|
||||||
private final String expectedGenesisHash;
|
private final String expectedGenesisHash;
|
||||||
@ -99,7 +113,7 @@ public class PirateLightClient extends BitcoinyBlockchainProvider {
|
|||||||
private Bitcoiny blockchain;
|
private Bitcoiny blockchain;
|
||||||
|
|
||||||
private final Object serverLock = new Object();
|
private final Object serverLock = new Object();
|
||||||
private Server currentServer;
|
private ChainableServer currentServer;
|
||||||
private ManagedChannel channel;
|
private ManagedChannel channel;
|
||||||
private int nextId = 1;
|
private int nextId = 1;
|
||||||
|
|
||||||
@ -525,6 +539,24 @@ public class PirateLightClient extends BitcoinyBlockchainProvider {
|
|||||||
throw new ForeignBlockchainException.NetworkException(String.format("Unexpected error code from Pirate Chain broadcastTransaction gRPC: %d", sendResponse.getErrorCode()));
|
throw new ForeignBlockchainException.NetworkException(String.format("Unexpected error code from Pirate Chain broadcastTransaction gRPC: %d", sendResponse.getErrorCode()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<ChainableServer> getServers() {
|
||||||
|
return this.servers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ChainableServer> getRemainingServers() {
|
||||||
|
return this.remainingServers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<ChainableServer> getUselessServers() {
|
||||||
|
return this.uselessServers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChainableServer getCurrentServer() { return this.currentServer; }
|
||||||
|
|
||||||
// Class-private utility methods
|
// Class-private utility methods
|
||||||
|
|
||||||
|
|
||||||
@ -544,7 +576,7 @@ public class PirateLightClient extends BitcoinyBlockchainProvider {
|
|||||||
if (!this.remainingServers.isEmpty()) {
|
if (!this.remainingServers.isEmpty()) {
|
||||||
long averageResponseTime = this.currentServer.averageResponseTime();
|
long averageResponseTime = this.currentServer.averageResponseTime();
|
||||||
if (averageResponseTime > MAX_AVG_RESPONSE_TIME) {
|
if (averageResponseTime > MAX_AVG_RESPONSE_TIME) {
|
||||||
LOGGER.info("Slow average response time {}ms from {} - trying another server...", averageResponseTime, this.currentServer.hostname);
|
LOGGER.info("Slow average response time {}ms from {} - trying another server...", averageResponseTime, this.currentServer.getHostName());
|
||||||
this.closeServer();
|
this.closeServer();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -568,11 +600,11 @@ public class PirateLightClient extends BitcoinyBlockchainProvider {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
while (!this.remainingServers.isEmpty()) {
|
while (!this.remainingServers.isEmpty()) {
|
||||||
Server server = this.remainingServers.remove(RANDOM.nextInt(this.remainingServers.size()));
|
ChainableServer server = this.remainingServers.remove(RANDOM.nextInt(this.remainingServers.size()));
|
||||||
LOGGER.trace(() -> String.format("Connecting to %s", server));
|
LOGGER.trace(() -> String.format("Connecting to %s", server));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.channel = ManagedChannelBuilder.forAddress(server.hostname, server.port).build();
|
this.channel = ManagedChannelBuilder.forAddress(server.getHostName(), server.getPort()).build();
|
||||||
|
|
||||||
CompactTxStreamerGrpc.CompactTxStreamerBlockingStub stub = CompactTxStreamerGrpc.newBlockingStub(this.channel);
|
CompactTxStreamerGrpc.CompactTxStreamerBlockingStub stub = CompactTxStreamerGrpc.newBlockingStub(this.channel);
|
||||||
LightdInfo lightdInfo = stub.getLightdInfo(Empty.newBuilder().build());
|
LightdInfo lightdInfo = stub.getLightdInfo(Empty.newBuilder().build());
|
||||||
@ -604,7 +636,7 @@ public class PirateLightClient extends BitcoinyBlockchainProvider {
|
|||||||
* Closes connection to <tt>server</tt> if it is currently connected server.
|
* Closes connection to <tt>server</tt> if it is currently connected server.
|
||||||
* @param server
|
* @param server
|
||||||
*/
|
*/
|
||||||
private void closeServer(Server server) {
|
private void closeServer(ChainableServer server) {
|
||||||
synchronized (this.serverLock) {
|
synchronized (this.serverLock) {
|
||||||
if (this.currentServer == null || !this.currentServer.equals(server) || this.channel == null) {
|
if (this.currentServer == null || !this.currentServer.equals(server) || this.channel == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -7,7 +7,7 @@ import org.bitcoinj.params.RegTestParams;
|
|||||||
import org.bitcoinj.params.TestNet3Params;
|
import org.bitcoinj.params.TestNet3Params;
|
||||||
import org.libdohj.params.RavencoinMainNetParams;
|
import org.libdohj.params.RavencoinMainNetParams;
|
||||||
import org.qortal.crosschain.ElectrumX.Server;
|
import org.qortal.crosschain.ElectrumX.Server;
|
||||||
import org.qortal.crosschain.ElectrumX.Server.ConnectionType;
|
import org.qortal.crosschain.ChainableServer.ConnectionType;
|
||||||
import org.qortal.settings.Settings;
|
import org.qortal.settings.Settings;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
package org.qortal.crosschain;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
|
public class ServerConfigurationInfo {
|
||||||
|
|
||||||
|
private List<ServerInfo> servers;
|
||||||
|
private List<ServerInfo> remainingServers;
|
||||||
|
private List<ServerInfo> uselessServers;
|
||||||
|
|
||||||
|
public ServerConfigurationInfo() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerConfigurationInfo(
|
||||||
|
List<ServerInfo> servers,
|
||||||
|
List<ServerInfo> remainingServers,
|
||||||
|
List<ServerInfo> uselessServers) {
|
||||||
|
this.servers = servers;
|
||||||
|
this.remainingServers = remainingServers;
|
||||||
|
this.uselessServers = uselessServers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ServerInfo> getServers() {
|
||||||
|
return servers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ServerInfo> getRemainingServers() {
|
||||||
|
return remainingServers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ServerInfo> getUselessServers() {
|
||||||
|
return uselessServers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
ServerConfigurationInfo that = (ServerConfigurationInfo) o;
|
||||||
|
return Objects.equals(servers, that.servers) && Objects.equals(remainingServers, that.remainingServers) && Objects.equals(uselessServers, that.uselessServers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(servers, remainingServers, uselessServers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ServerConfigurationInfo{" +
|
||||||
|
"servers=" + servers +
|
||||||
|
", remainingServers=" + remainingServers +
|
||||||
|
", uselessServers=" + uselessServers +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,7 @@ import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.qortal.crosschain.Bitcoin.BitcoinNet;
|
import org.qortal.crosschain.Bitcoin.BitcoinNet;
|
||||||
import org.qortal.crosschain.*;
|
import org.qortal.crosschain.*;
|
||||||
import org.qortal.crosschain.ElectrumX.Server.ConnectionType;
|
import org.qortal.crosschain.ChainableServer.ConnectionType;
|
||||||
import org.qortal.utils.BitTwiddling;
|
import org.qortal.utils.BitTwiddling;
|
||||||
|
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
|
Loading…
Reference in New Issue
Block a user