Merge pull request #6313 from ghubstan/remove-subproject-daonode

Remove subproject daonode
This commit is contained in:
Christoph Atteneder 2022-08-17 13:30:44 +02:00 committed by GitHub
commit 869fdad705
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 0 additions and 12403 deletions

View File

@ -54,7 +54,6 @@ configure(subprojects) {
javafxVersion = '16' javafxVersion = '16'
javaxAnnotationVersion = '1.2' javaxAnnotationVersion = '1.2'
jcsvVersion = '1.4.0' jcsvVersion = '1.4.0'
jerseyVersion = '3.0.4'
jetbrainsAnnotationsVersion = '13.0' jetbrainsAnnotationsVersion = '13.0'
jfoenixVersion = '9.0.10' jfoenixVersion = '9.0.10'
joptVersion = '5.0.4' joptVersion = '5.0.4'
@ -77,7 +76,6 @@ configure(subprojects) {
slf4jVersion = '1.7.30' slf4jVersion = '1.7.30'
sparkVersion = '2.5.2' sparkVersion = '2.5.2'
springBootVersion = '2.5.6' springBootVersion = '2.5.6'
swaggerVersion = '2.2.0'
os = osdetector.os == 'osx' ? 'mac' : osdetector.os == 'windows' ? 'win' : osdetector.os os = osdetector.os == 'osx' ? 'mac' : osdetector.os == 'windows' ? 'win' : osdetector.os
} }
@ -105,7 +103,6 @@ configure([project(':cli'),
project(':seednode'), project(':seednode'),
project(':statsnode'), project(':statsnode'),
project(':pricenode'), project(':pricenode'),
project(':daonode'),
project(':apitest')]) { project(':apitest')]) {
apply plugin: 'application' apply plugin: 'application'
@ -689,56 +686,6 @@ configure(project(':seednode')) {
} }
} }
configure(project(':daonode')) {
apply plugin: 'com.github.johnrengelman.shadow'
mainClassName = 'bisq.daoNode.DaoNodeRestApiApplication'
dependencies {
implementation project(':common')
implementation project(':proto')
implementation project(':p2p')
implementation project(':core')
implementation "com.google.guava:guava:$guavaVersion"
implementation("com.google.inject:guice:$guiceVersion") {
exclude(module: 'guava')
}
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
compileOnly "org.projectlombok:lombok:$lombokVersion"
implementation "ch.qos.logback:logback-classic:$logbackVersion"
implementation "ch.qos.logback:logback-core:$logbackVersion"
implementation "org.slf4j:slf4j-api:$slf4jVersion"
/* implementation("com.fasterxml.jackson.core:jackson-core:$jacksonVersion")
implementation("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion")
implementation("com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion")
implementation "com.google.protobuf:protobuf-java-util:$protobufVersion"*/
implementation("org.glassfish.jersey.containers:jersey-container-jdk-http:$jerseyVersion")
implementation("org.glassfish.jersey.media:jersey-media-json-jackson:$jerseyVersion")
implementation("org.glassfish.jersey.inject:jersey-hk2:$jerseyVersion")
implementation("org.glassfish.jaxb:jaxb-runtime:3.0.2")
implementation("io.swagger.core.v3:swagger-jaxrs2-jakarta:$swaggerVersion")
testImplementation "org.mockito:mockito-core:$mockitoVersion"
testCompileOnly "org.projectlombok:lombok:$lombokVersion"
testImplementation "org.apache.httpcomponents:httpclient:$httpclientVersion"
testImplementation "org.junit.jupiter:junit-jupiter-api:$jupiterVersion"
testImplementation "org.junit.jupiter:junit-jupiter-params:$jupiterVersion"
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$jupiterVersion")
}
test {
useJUnitPlatform()
testLogging {
events "passed", "skipped", "failed"
}
}
}
configure(project(':statsnode')) { configure(project(':statsnode')) {
mainClassName = 'bisq.statistics.StatisticsMain' mainClassName = 'bisq.statistics.StatisticsMain'

View File

@ -1,128 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.daonode;
import bisq.common.config.Config;
import java.net.URI;
import java.util.function.Consumer;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import bisq.daonode.endpoints.AccountAgeApi;
import bisq.daonode.endpoints.BondedReputationApi;
import bisq.daonode.endpoints.ProofOfBurnApi;
import bisq.daonode.endpoints.SignedWitnessApi;
import bisq.daonode.error.CustomExceptionMapper;
import bisq.daonode.error.StatusException;
import bisq.daonode.util.StaticFileHandler;
import com.sun.net.httpserver.HttpServer;
import org.glassfish.jersey.jdkhttp.JdkHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
/**
* Application to start and config the rest service.
* This creates a rest service for clients to connect and for users to browse the documentation.
* <p>
* Swagger doc are available at <a href="http://localhost:8082/doc/v1/index.html">REST API documentation</a>
*/
@Slf4j
public class DaoNodeRestApiApplication extends ResourceConfig {
@Getter
private static String baseUrl;
public static void main(String[] args) throws Exception {
DaoNodeRestApiApplication daoNodeRestApiApplication = new DaoNodeRestApiApplication();
daoNodeRestApiApplication.startDaoNode(args, config -> {
daoNodeRestApiApplication
.register(CustomExceptionMapper.class)
.register(StatusException.StatusExceptionMapper.class)
.register(ProofOfBurnApi.class)
.register(BondedReputationApi.class)
.register(AccountAgeApi.class)
.register(SignedWitnessApi.class)
.register(SwaggerResolution.class);
daoNodeRestApiApplication.startServer(config.daoNodeApiUrl, config.daoNodeApiPort);
});
}
@Getter
private final ServiceNode serviceNode;
private HttpServer httpServer;
public DaoNodeRestApiApplication() {
serviceNode = new ServiceNode();
}
private void startDaoNode(String[] args, Consumer<Config> configConsumer) {
new Thread(() -> {
serviceNode.execute(args);
configConsumer.accept(serviceNode.getConfig());
try {
// Keep running
Thread.currentThread().setName("daoNodeThread");
Thread.currentThread().join();
} catch (InterruptedException e) {
log.error("daoNodeThread interrupted", e);
e.printStackTrace();
shutDown();
}
}).start();
}
private void startServer(String url, int port) {
baseUrl = url + ":" + port + "/api/v1";
httpServer = JdkHttpServerFactory.createHttpServer(URI.create(baseUrl), this);
httpServer.createContext("/doc", new StaticFileHandler("/doc/v1/"));
Runtime.getRuntime().addShutdownHook(new Thread(this::shutDown));
log.info("Server started at {}.", baseUrl);
// block and wait shut down signal, like CTRL+C
try {
Thread.currentThread().setName("serverThread");
Thread.currentThread().join();
} catch (InterruptedException e) {
log.error("serverThread interrupted", e);
System.exit(1);
}
shutDown();
}
private void shutDown() {
if (serviceNode != null) {
serviceNode.gracefulShutDown(this::stopServer);
} else {
stopServer();
}
}
private void stopServer() {
if (httpServer != null) {
httpServer.stop(1);
}
}
}

View File

@ -1,210 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.daonode;
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.app.TorSetup;
import bisq.core.app.misc.AppSetupWithP2PAndDAO;
import bisq.core.app.misc.ExecutableForAppWithP2p;
import bisq.core.app.misc.ModuleForAppWithP2p;
import bisq.core.dao.governance.bond.reputation.BondedReputationRepository;
import bisq.core.dao.state.DaoStateService;
import bisq.core.dao.state.DaoStateSnapshotService;
import bisq.core.user.Cookie;
import bisq.core.user.CookieKey;
import bisq.core.user.Preferences;
import bisq.core.user.User;
import bisq.network.p2p.P2PService;
import bisq.network.p2p.P2PServiceListener;
import bisq.network.p2p.peers.PeerManager;
import bisq.common.Timer;
import bisq.common.UserThread;
import bisq.common.app.AppModule;
import bisq.common.app.Version;
import bisq.common.config.BaseCurrencyNetwork;
import bisq.common.config.Config;
import bisq.common.handlers.ResultHandler;
import com.google.inject.Key;
import com.google.inject.name.Names;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
//todo not sure if the restart handling from seed nodes is required
@Slf4j
public class ServiceNode extends ExecutableForAppWithP2p {
private static final long CHECK_CONNECTION_LOSS_SEC = 30;
private Timer checkConnectionLossTime;
@Getter
private DaoStateService daoStateService;
@Getter
private BondedReputationRepository bondedReputationRepository;
@Getter
private AccountAgeWitnessService accountAgeWitnessService;
public ServiceNode() {
super("Bisq Dao Node", "bisq-dao-node", "bisq_dao_node", Version.VERSION);
}
public Config getConfig() {
return config;
}
@Override
protected void doExecute() {
super.doExecute();
checkMemory(config, this);
}
@Override
protected void launchApplication() {
UserThread.execute(() -> {
try {
onApplicationLaunched();
} catch (Exception e) {
e.printStackTrace();
}
});
}
///////////////////////////////////////////////////////////////////////////////////////////
// We continue with a series of synchronous execution tasks
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected AppModule getModule() {
return new ModuleForAppWithP2p(config);
}
@Override
protected void applyInjector() {
super.applyInjector();
injector.getInstance(DaoStateSnapshotService.class).setDaoRequiresRestartHandler(this::gracefulShutDown);
}
@Override
protected void startApplication() {
super.startApplication();
Cookie cookie = injector.getInstance(User.class).getCookie();
cookie.getAsOptionalBoolean(CookieKey.CLEAN_TOR_DIR_AT_RESTART).ifPresent(wasCleanTorDirSet -> {
if (wasCleanTorDirSet) {
injector.getInstance(TorSetup.class).cleanupTorFiles(() -> {
log.info("Tor directory reset");
cookie.remove(CookieKey.CLEAN_TOR_DIR_AT_RESTART);
}, log::error);
}
});
injector.getInstance(Preferences.class).setUseFullModeDaoMonitor(false);
injector.getInstance(AppSetupWithP2PAndDAO.class).start();
daoStateService = injector.getInstance(DaoStateService.class);
accountAgeWitnessService = injector.getInstance(AccountAgeWitnessService.class);
bondedReputationRepository = injector.getInstance(BondedReputationRepository.class);
injector.getInstance(P2PService.class).addP2PServiceListener(new P2PServiceListener() {
@Override
public void onDataReceived() {
// Do nothing
}
@Override
public void onNoSeedNodeAvailable() {
// Do nothing
}
@Override
public void onNoPeersAvailable() {
// Do nothing
}
@Override
public void onUpdatedDataReceived() {
// Do nothing
}
@Override
public void onTorNodeReady() {
// Do nothing
}
@Override
public void onHiddenServicePublished() {
boolean preventPeriodicShutdownAtSeedNode = injector.getInstance(Key.get(boolean.class,
Names.named(Config.PREVENT_PERIODIC_SHUTDOWN_AT_SEED_NODE)));
if (!preventPeriodicShutdownAtSeedNode) {
startShutDownInterval(ServiceNode.this);
}
UserThread.runAfter(() -> setupConnectionLossCheck(), 60);
accountAgeWitnessService.onAllServicesInitialized();
}
@Override
public void onSetupFailed(Throwable throwable) {
// Do nothing
}
@Override
public void onRequestCustomBridges() {
// Do nothing
}
});
}
private void setupConnectionLossCheck() {
// For dev testing (usually on BTC_REGTEST) we don't want to get the seed shut
// down as it is normal that the seed is the only actively running node.
if (Config.baseCurrencyNetwork() == BaseCurrencyNetwork.BTC_REGTEST) {
return;
}
if (checkConnectionLossTime != null) {
return;
}
checkConnectionLossTime = UserThread.runPeriodically(() -> {
if (injector.getInstance(PeerManager.class).getNumAllConnectionsLostEvents() > 1) {
// We set a flag to clear tor cache files at re-start. We cannot clear it now as Tor is used and
// that can cause problems.
injector.getInstance(User.class).getCookie().putAsBoolean(CookieKey.CLEAN_TOR_DIR_AT_RESTART, true);
shutDown(this);
}
}, CHECK_CONNECTION_LOSS_SEC);
}
private void gracefulShutDown() {
gracefulShutDown(() -> {
});
}
@Override
public void gracefulShutDown(ResultHandler resultHandler) {
super.gracefulShutDown(resultHandler);
}
}

View File

@ -1,71 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.daonode;
import lombok.extern.slf4j.Slf4j;
import io.swagger.v3.core.util.Json;
import io.swagger.v3.jaxrs2.Reader;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.integration.SwaggerConfiguration;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.servers.Server;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
@Slf4j
@Path("openapi.json")
@Produces(MediaType.APPLICATION_JSON)
@Hidden
public class SwaggerResolution {
private static String swaggerJson;
@GET
public String swagIt(@Context Application application) {
if (swaggerJson == null) {
try {
OpenAPI api = new OpenAPI();
Info info = new Info()
.title("Bisq DAO node REST API")
.description("This is the rest API description for the Bisq DAO node, For more Information about Bisq, see https://bisq.network")
.license(new License()
.name("GNU Affero General Public License")
.url("https://github.com/bisq-network/bisq2/blob/main/LICENSE"));
api.info(info).addServersItem(new Server().url(DaoNodeRestApiApplication.getBaseUrl()));
SwaggerConfiguration configuration = new SwaggerConfiguration().openAPI(api);
Reader reader = new Reader(configuration);
OpenAPI openAPI = reader.read(application.getClasses());
swaggerJson = Json.pretty(openAPI);
} catch (Exception exception) {
log.error("", exception);
throw new RuntimeException(exception);
}
}
return swaggerJson;
}
}

View File

@ -1,48 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.daonode.dto;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import io.swagger.v3.oas.annotations.media.Schema;
/**
* Minimal data required for Bisq 2 bonded reputation use case.
* Need to be in sync with the Bisq 2 BondedReputationDto class.
*/
@Getter
@Slf4j
@Schema(title = "BondedReputation")
public class BondedReputationDto {
private final long amount;
private final long time;
private final String hash;
private final int blockHeight;
private final int lockTime;
public BondedReputationDto(long amount, long time, String hash, int blockHeight, int lockTime) {
this.amount = amount;
this.time = time;
this.hash = hash;
this.blockHeight = blockHeight;
this.lockTime = lockTime;
}
}

View File

@ -1,44 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.daonode.dto;
import lombok.Getter;
import io.swagger.v3.oas.annotations.media.Schema;
/**
* Minimal data required for Bisq 2 proof of burn use case.
* Need to be in sync with the Bisq 2 ProofOfBurnDto class.
*/
@Getter
@Schema(title = "ProofOfBurn")
public class ProofOfBurnDto {
private final long amount;
private final long time;
private final String hash;
private final int blockHeight;
public ProofOfBurnDto(long amount, long time, String hash, int blockHeight) {
this.amount = amount;
this.time = time;
this.hash = hash;
this.blockHeight = blockHeight;
}
}

View File

@ -1,76 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.daonode.endpoints;
import bisq.core.account.witness.AccountAgeWitness;
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkNotNull;
import bisq.daonode.DaoNodeRestApiApplication;
import bisq.daonode.ServiceNode;
import bisq.daonode.dto.ProofOfBurnDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
/**
* Endpoint for getting the account age date from a given hash as hex string.
* Used for reputation system in Bisq 2.
* <a href="http://localhost:8082/api/v1/account-age/get-date/dd75a7175c7c83fe9a4729e36b85f5fbc44e29ae">Request with hash</a>
*/
@Slf4j
@Path("/account-age")
@Produces(MediaType.TEXT_PLAIN)
@Tag(name = "Account age API")
public class AccountAgeApi {
private static final String DESC_HASH = "The hash of the account age witness as hex string";
private final ServiceNode serviceNode;
public AccountAgeApi(@Context Application application) {
serviceNode = ((DaoNodeRestApiApplication) application).getServiceNode();
}
@Operation(description = "Request the account age date")
@ApiResponse(responseCode = "200", description = "The account age date",
content = {@Content(mediaType = MediaType.TEXT_PLAIN,
schema = @Schema(allOf = ProofOfBurnDto.class))}
)
@GET
@Path("get-date/{hash}")
public Long getDate(@Parameter(description = DESC_HASH)
@PathParam("hash")
String hash) {
return checkNotNull(serviceNode.getAccountAgeWitnessService()).getWitnessByHashAsHex(hash)
.map(AccountAgeWitness::getDate)
.orElse(-1L);
}
}

View File

@ -1,103 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.daonode.endpoints;
import bisq.core.dao.governance.bond.reputation.BondedReputationRepository;
import bisq.core.dao.state.DaoStateService;
import bisq.core.dao.state.model.blockchain.Tx;
import bisq.common.util.Hex;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import bisq.daonode.DaoNodeRestApiApplication;
import bisq.daonode.ServiceNode;
import bisq.daonode.dto.BondedReputationDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
/**
* Endpoint for getting the bonded reputation data from a given block height.
* Used for reputation system in Bisq 2.
* <a href="http://localhost:8082/api/v1/bonded-reputation/get-bonded-reputation/0">Request with block height 0</a>
*/
@Slf4j
@Path("/bonded-reputation")
@Produces(MediaType.APPLICATION_JSON)
@Tag(name = "Bonded reputation API")
public class BondedReputationApi {
private static final String DESC_BLOCK_HEIGHT = "The block height from which we request the bonded reputation data";
private final BondedReputationRepository bondedReputationRepository;
private final DaoStateService daoStateService;
public BondedReputationApi(@Context Application application) {
ServiceNode serviceNode = ((DaoNodeRestApiApplication) application).getServiceNode();
daoStateService = serviceNode.getDaoStateService();
bondedReputationRepository = serviceNode.getBondedReputationRepository();
}
@Operation(description = "Request the bonded reputation data")
@ApiResponse(responseCode = "200", description = "The bonded reputation data",
content = {@Content(mediaType = MediaType.APPLICATION_JSON,
schema = @Schema(allOf = BondedReputationDto.class))}
)
@GET
@Path("get-bonded-reputation/{block-height}")
public List<BondedReputationDto> getBondedReputation(@Parameter(description = DESC_BLOCK_HEIGHT)
@PathParam("block-height")
int fromBlockHeight) {
return bondedReputationRepository.getActiveBonds().stream()
.map(bondedReputation -> {
Optional<Tx> optionalTx = daoStateService.getTx(bondedReputation.getLockupTxId());
if (optionalTx.isEmpty()) {
return null;
}
Tx tx = optionalTx.get();
int blockHeight = tx.getBlockHeight();
if (blockHeight >= fromBlockHeight) {
return new BondedReputationDto(bondedReputation.getAmount(),
tx.getTime(),
Hex.encode(bondedReputation.getBondedAsset().getHash()),
blockHeight,
bondedReputation.getLockTime()
);
} else {
return null;
}
}).filter(Objects::nonNull)
.collect(Collectors.toList());
}
}

View File

@ -1,85 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.daonode.endpoints;
import bisq.core.dao.governance.proofofburn.ProofOfBurnService;
import bisq.common.util.Hex;
import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkNotNull;
import bisq.daonode.DaoNodeRestApiApplication;
import bisq.daonode.ServiceNode;
import bisq.daonode.dto.ProofOfBurnDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
/**
* Endpoint for getting the proof of burn data from a given block height.
* Used for reputation system in Bisq 2.
* <a href="http://localhost:8082/api/v1/proof-of-burn/get-proof-of-burn/0">Request with block height 0</a>
*/
@Slf4j
@Path("/proof-of-burn")
@Produces(MediaType.APPLICATION_JSON)
@Tag(name = "Proof of burn API")
public class ProofOfBurnApi {
private static final String DESC_BLOCK_HEIGHT = "The block height from which we request the proof of burn data";
private final ServiceNode serviceNode;
public ProofOfBurnApi(@Context Application application) {
serviceNode = ((DaoNodeRestApiApplication) application).getServiceNode();
}
@Operation(description = "Request the proof of burn data")
@ApiResponse(responseCode = "200", description = "The proof of burn data",
content = {@Content(mediaType = MediaType.APPLICATION_JSON,
schema = @Schema(allOf = ProofOfBurnDto.class))}
)
@GET
@Path("get-proof-of-burn/{block-height}")
public List<ProofOfBurnDto> getProofOfBurn(@Parameter(description = DESC_BLOCK_HEIGHT)
@PathParam("block-height")
int fromBlockHeight) {
return checkNotNull(serviceNode.getDaoStateService()).getProofOfBurnTxs().stream()
.filter(tx -> tx.getBlockHeight() >= fromBlockHeight)
.map(tx -> new ProofOfBurnDto(tx.getBurntBsq(),
tx.getTime(),
Hex.encode(ProofOfBurnService.getHashFromOpReturnData(tx)),
tx.getBlockHeight()))
.collect(Collectors.toList());
}
}

View File

@ -1,77 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.daonode.endpoints;
import bisq.core.account.witness.AccountAgeWitnessService;
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkNotNull;
import bisq.daonode.DaoNodeRestApiApplication;
import bisq.daonode.ServiceNode;
import bisq.daonode.dto.ProofOfBurnDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
/**
* Endpoint for getting the signed witness date from a given hash as hex string.
* Used for reputation system in Bisq 2.
* <a href="http://localhost:8082/api/v1/signed-witness/get-date/dd75a7175c7c83fe9a4729e36b85f5fbc44e29ae">Request with hash</a>
*/
@Slf4j
@Path("/signed-witness")
@Produces(MediaType.TEXT_PLAIN)
@Tag(name = "Signed witness API")
public class SignedWitnessApi {
private static final String DESC_HASH = "The hash of the signed account age witness as hex string";
private final ServiceNode serviceNode;
public SignedWitnessApi(@Context Application application) {
serviceNode = ((DaoNodeRestApiApplication) application).getServiceNode();
}
@Operation(description = "Request the signed witness date")
@ApiResponse(responseCode = "200", description = "The signed witness date",
content = {@Content(mediaType = MediaType.TEXT_PLAIN,
schema = @Schema(allOf = ProofOfBurnDto.class))}
)
@GET
@Path("get-date/{hash}")
public Long getDate(@Parameter(description = DESC_HASH)
@PathParam("hash")
String hash) {
AccountAgeWitnessService accountAgeWitnessService = checkNotNull(serviceNode.getAccountAgeWitnessService());
return accountAgeWitnessService.getWitnessByHashAsHex(hash)
.map(accountAgeWitnessService::getWitnessSignDate)
.orElse(-1L);
}
}

View File

@ -1,38 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.daonode.error;
import lombok.extern.slf4j.Slf4j;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;
@Slf4j
@Provider
public class CustomExceptionMapper implements ExceptionMapper<Exception> {
@Override
public Response toResponse(Exception exception) {
log.error("", exception);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(new ErrorMessage(exception.getMessage()))
.build();
}
}

View File

@ -1,30 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.daonode.error;
import lombok.Getter;
@Getter
public class ErrorMessage {
private final String error;
public ErrorMessage(String error) {
this.error = error;
}
}

View File

@ -1,55 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.daonode.error;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;
@Slf4j
@Provider
public class StatusException extends RuntimeException {
@Getter
@Setter
protected Response.Status httpStatus;
public StatusException() {
}
public StatusException(Response.Status httpStatus, String message) {
super(message);
this.httpStatus = httpStatus;
}
public static class StatusExceptionMapper implements ExceptionMapper<StatusException> {
@Override
public Response toResponse(StatusException exception) {
log.error("", exception);
return Response.status(exception.getHttpStatus())
.entity(new ErrorMessage(exception.getMessage()))
.build();
}
}
}

View File

@ -1,108 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.daonode.util;
import java.net.URI;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
/**
* JDK Server needs handler for serving files, will change in JDK 18
* Currently this is only to serve the swagger-ui content to the client.
* So any call to this handler must begin with api/v1. We keep v1 in case
* we will have incompatible changes in the future.
* This handler is limited to html,css,json and javascript files.
*/
@Slf4j
public class StaticFileHandler implements HttpHandler {
private static final String NOT_FOUND = "404 (Not Found)\n";
public static final String[] VALID_SUFFIX = {".html", ".json", ".css", ".js"};
@Getter
protected final String rootContext;
public StaticFileHandler(String rootContext) {
this.rootContext = rootContext;
}
public void handle(HttpExchange exchange) throws IOException {
URI uri = exchange.getRequestURI();
log.debug("requesting: " + uri.getPath());
String filename = uri.getPath();
if (filename == null || !filename.startsWith(rootContext) ||
Arrays.stream(VALID_SUFFIX).noneMatch(filename::endsWith)) {
respond404(exchange);
return;
}
// resource loading without leading slash
String resourceName = filename.replace("..", "");
if (filename.charAt(0) == '/') {
resourceName = filename.substring(1);
}
// we are using getResourceAsStream to ultimately prevent load from parent directories
try (InputStream resource = getClass().getClassLoader().getResourceAsStream(resourceName)) {
if (resource == null) {
respond404(exchange);
return;
}
log.debug("sending: " + resourceName);
// Object exists and is a file: accept with response code 200.
String mime = "text/html";
if (resourceName.endsWith(".js")) mime = "application/javascript";
if (resourceName.endsWith(".json")) mime = "application/json";
if (resourceName.endsWith(".css")) mime = "text/css";
if (resourceName.endsWith(".png")) mime = "image/png";
Headers headers = exchange.getResponseHeaders();
headers.set("Content-Type", mime);
headers.add("Cache-Control", "max-age=3600"); // cache static content on browser for 3600 seconds
exchange.sendResponseHeaders(200, 0);
try (OutputStream outputStream = exchange.getResponseBody()) {
byte[] buffer = new byte[0x10000];
int count;
while ((count = resource.read(buffer)) >= 0) {
outputStream.write(buffer, 0, count);
}
}
}
}
private void respond404(HttpExchange exchange) throws IOException {
// Object does not exist or is not a file: reject with 404 error.
exchange.sendResponseHeaders(404, NOT_FOUND.length());
try (OutputStream outputStream = exchange.getResponseBody()) {
outputStream.write(NOT_FOUND.getBytes());
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 665 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 628 B

View File

@ -1,16 +0,0 @@
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
background: #fafafa;
}

View File

@ -1,19 +0,0 @@
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="./swagger-ui.css"/>
<link rel="stylesheet" type="text/css" href="index.css"/>
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32"/>
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16"/>
</head>
<body>
<div id="swagger-ui"></div>
<script src="./swagger-ui-bundle.js" charset="UTF-8"></script>
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"></script>
<script src="./swagger-initializer.js" charset="UTF-8"></script>
</body>
</html>

View File

@ -1,80 +0,0 @@
<!doctype html>
<html lang="en-US">
<head>
<title>Swagger UI: OAuth2 Redirect</title>
</head>
<body>
<script>
'use strict';
function run () {
var oauth2 = window.opener.swaggerUIRedirectOauth2;
var sentState = oauth2.state;
var redirectUrl = oauth2.redirectUrl;
var isValid, qp, arr;
if (/code|token|error/.test(window.location.hash)) {
qp = window.location.hash.substring(1);
} else {
qp = location.search.substring(1);
}
arr = qp.split("&");
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
qp = qp ? JSON.parse('{' + arr.join() + '}',
function (key, value) {
return key === "" ? value : decodeURIComponent(value);
}
) : {};
isValid = qp.state === sentState;
if ((
oauth2.auth.schema.get("flow") === "accessCode" ||
oauth2.auth.schema.get("flow") === "authorizationCode" ||
oauth2.auth.schema.get("flow") === "authorization_code"
) && !oauth2.auth.code) {
if (!isValid) {
oauth2.errCb({
authId: oauth2.auth.name,
source: "auth",
level: "warning",
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
});
}
if (qp.code) {
delete oauth2.state;
oauth2.auth.code = qp.code;
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
} else {
let oauthErrorMsg;
if (qp.error) {
oauthErrorMsg = "["+qp.error+"]: " +
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
(qp.error_uri ? "More info: "+qp.error_uri : "");
}
oauth2.errCb({
authId: oauth2.auth.name,
source: "auth",
level: "error",
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server"
});
}
} else {
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
}
window.close();
}
if (document.readyState !== 'loading') {
run();
} else {
document.addEventListener('DOMContentLoaded', function () {
run();
});
}
</script>
</body>
</html>

View File

@ -1,20 +0,0 @@
window.onload = function() {
//<editor-fold desc="Changeable Configuration Block">
// the following lines will be replaced by docker/configurator, when it runs in a docker-container
window.ui = SwaggerUIBundle({
url: "/api/v1/openapi.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});
//</editor-fold>
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%highlight(%d{MMM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{15}: %msg %xEx%n)</pattern>
</encoder>
</appender>
<root level="TRACE">
<appender-ref ref="CONSOLE_APPENDER"/>
</root>
<logger name="com.msopentech.thali.toronionproxy.OnionProxyManagerEventHandler" level="INFO"/>
</configuration>

View File

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--
The :daemon & :cli jars contain their own logback.xml config files, which causes chatty logback startup.
To avoid chatty logback msgs during its configuration, pass logback.configurationFile as a system property:
-Dlogback.configurationFile=apitest/build/resources/main/logback.xml
The gradle build file takes care of adding this system property to the bisq-apitest script.
-->
<appender name="CONSOLE_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%highlight(%d{MMM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{30}: %msg %xEx%n)</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE_APPENDER"/>
</root>
<logger name="io.grpc.netty" level="WARN"/>
</configuration>

View File

@ -11,7 +11,6 @@ include 'pricenode'
include 'relay' include 'relay'
include 'seednode' include 'seednode'
include 'statsnode' include 'statsnode'
include 'daonode'
include 'apitest' include 'apitest'
rootProject.name = 'bisq' rootProject.name = 'bisq'