diff --git a/.gitignore b/.gitignore index cd7aac982d..95cdef3878 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,4 @@ nbactions.xml **/swagger-codegen-cli-*.jar **/.swagger-codegen /apl-api2/src/gen/ +/apollo-mariadb diff --git a/apl-api/src/main/java/com/apollocurrency/aplwallet/api/p2p/PeerInfo.java b/apl-api/src/main/java/com/apollocurrency/aplwallet/api/p2p/PeerInfo.java index 13272a89a0..f6757e327d 100644 --- a/apl-api/src/main/java/com/apollocurrency/aplwallet/api/p2p/PeerInfo.java +++ b/apl-api/src/main/java/com/apollocurrency/aplwallet/api/p2p/PeerInfo.java @@ -167,11 +167,23 @@ public class PeerInfo extends BaseP2PResponse { /** * PEM-encoded X.509 Certificate of host as String, including * BEGIN-CETIFICATE and END-CERTIFICATE marks. Certificate - * should be verified and used for private key cryptography. Certificate - * also contains some important attributes, that is used widely in communications. + * should be verified. CA-signed certificate should be verified using CA x.509 cert. + * Self-signed certificate should be verified by checking signature of "blockTime" field + * with proposed self-signed certificate to ensure private key ownership. * New! */ private String X509_cert; + /** + * Epoch time of the node. Needed to approve private key ownership and make + * replay attacks less possible + */ + private Integer epochTime; + /** + * HEX string represenataion of the signature of blockTime (as 4 bytes in netowk order). + * Signature algorithm is the default for given public key type of X.509 certiificate, + * for more information please see fb-cryptoo library documentation + */ + private String epochTimeSigantureHex; /** * blacklist cause */ diff --git a/apl-api2/src/main/resources/META-INF/beans.xml b/apl-api2/src/main/resources/META-INF/beans.xml index e290abbacc..0178091e87 100644 --- a/apl-api2/src/main/resources/META-INF/beans.xml +++ b/apl-api2/src/main/resources/META-INF/beans.xml @@ -9,5 +9,6 @@ + \ No newline at end of file diff --git a/apl-core/pom.xml b/apl-core/pom.xml index c301f8d93d..9e62a1d390 100644 --- a/apl-core/pom.xml +++ b/apl-core/pom.xml @@ -29,6 +29,18 @@ apl-api2 ${project.version} + + + + io.firstbridge + fb-identity + + + + ch.qos.logback + logback-classic + + com.apollocurrency apl-db-updater @@ -59,11 +71,6 @@ ${smc-lib.version} - - - ch.qos.logback - logback-classic - org.slf4j slf4j-api diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerDb.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/dao/appdata/PeerDao.java similarity index 71% rename from apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerDb.java rename to apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/dao/appdata/PeerDao.java index f21f5895b2..f18033b177 100644 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerDb.java +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/dao/appdata/PeerDao.java @@ -15,15 +15,17 @@ */ /* - * Copyright © 2018 Apollo Foundation + * Copyright © 2018-2021 Apollo Foundation */ -package com.apollocurrency.aplwallet.apl.core.peer; +package com.apollocurrency.aplwallet.apl.core.dao.appdata; import com.apollocurrency.aplwallet.apl.core.db.DatabaseManager; +import com.apollocurrency.aplwallet.apl.util.db.TransactionalDataSource; +import com.apollocurrency.aplwallet.apl.core.entity.appdata.PeerEntity; +import com.apollocurrency.aplwallet.apl.core.peer.Peer; import com.apollocurrency.aplwallet.apl.util.annotation.DatabaseSpecificDml; import com.apollocurrency.aplwallet.apl.util.annotation.DmlMarker; -import com.apollocurrency.aplwallet.apl.util.db.TransactionalDataSource; import jakarta.inject.Inject; import jakarta.inject.Singleton; @@ -36,23 +38,32 @@ import java.util.List; @Singleton -public class PeerDb { +public class PeerDao { private final DatabaseManager databaseManager; @Inject - public PeerDb(DatabaseManager databaseManagerParam) { + public PeerDao(DatabaseManager databaseManagerParam) { databaseManager = databaseManagerParam; } - public List loadPeers() { - List peers = new ArrayList<>(); + + public List loadPeers() { + List peers = new ArrayList<>(); + TransactionalDataSource dataSource = databaseManager.getDataSource(); try (Connection con = dataSource.getConnection(); PreparedStatement pstmt = con.prepareStatement("SELECT * FROM peer"); ResultSet rs = pstmt.executeQuery()) { while (rs.next()) { - peers.add(new Entry(rs.getString("address"), rs.getLong("services"), rs.getInt("last_updated"))); + peers.add(new PeerEntity( + rs.getString("address"), + rs.getLong("services"), + rs.getInt("last_updated"), + rs.getString("x509pem"), + rs.getString("ip_and_port") + ) + ); } } catch (SQLException e) { throw new RuntimeException(e.toString(), e); @@ -60,7 +71,9 @@ public List loadPeers() { return peers; } - public void deletePeer(Entry peer) { + + public void deletePeer(PeerEntity peer) { + TransactionalDataSource dataSource = databaseManager.getDataSource(); try (Connection con = dataSource.getConnection()) { PreparedStatement pstmt = con.prepareStatement("DELETE FROM peer WHERE address = ?"); @@ -71,11 +84,13 @@ public void deletePeer(Entry peer) { } } - public void deletePeers(Collection peers) { + + public void deletePeers(Collection peers) { + TransactionalDataSource dataSource = databaseManager.getDataSource(); try (Connection con = dataSource.getConnection(); PreparedStatement pstmt = con.prepareStatement("DELETE FROM peer WHERE address = ?")) { - for (Entry peer : peers) { + for (PeerEntity peer : peers) { pstmt.setString(1, peer.getAddress()); pstmt.executeUpdate(); } @@ -84,18 +99,20 @@ public void deletePeers(Collection peers) { } } - public void updatePeers(Collection peers) { + public void updatePeers(Collection peers) { + TransactionalDataSource dataSource = databaseManager.getDataSource(); dataSource.begin(); try (Connection con = dataSource.getConnection(); @DatabaseSpecificDml(DmlMarker.MERGE) + PreparedStatement pstmt = con.prepareStatement("INSERT INTO peer " + "(address, services, last_updated) " + "VALUES(?, ?, ?) " + "ON DUPLICATE KEY UPDATE " + "address = VALUES(address), services = VALUES(services), last_updated = VALUES(last_updated)") ) { - for (Entry peer : peers) { + for (PeerEntity peer : peers) { pstmt.setString(1, peer.getAddress()); pstmt.setLong(2, peer.getServices()); pstmt.setInt(3, peer.getLastUpdated()); @@ -108,7 +125,9 @@ public void updatePeers(Collection peers) { } } - public void updatePeer(PeerImpl peer) { + + public void updatePeer(Peer peer) { + TransactionalDataSource dataSource = databaseManager.getDataSource(); dataSource.begin(); try (Connection con = dataSource.getConnection(); @@ -128,46 +147,4 @@ public void updatePeer(PeerImpl peer) { } } - static class Entry { - private final String address; - private final long services; - private final int lastUpdated; - - Entry(String address, long services, int lastUpdated) { - this.address = address; - this.services = services; - this.lastUpdated = lastUpdated; - } - - public String getAddress() { - return address; - } - - public long getServices() { - return services; - } - - public int getLastUpdated() { - return lastUpdated; - } - - @Override - public int hashCode() { - return address.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return (obj != null && (obj instanceof Entry) && address.equals(((Entry) obj).address)); - } - - @Override - public String toString() { - return "PeerEntry{" + - "address='" + address + '\'' + - ", services=" + services + - ", lastUpdated=" + lastUpdated + - '}'; - } - } } diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/dao/state/publickey/PublicKeyTableProducer.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/dao/state/publickey/PublicKeyTableProducer.java index eec7bbaf32..4337afe747 100644 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/dao/state/publickey/PublicKeyTableProducer.java +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/dao/state/publickey/PublicKeyTableProducer.java @@ -78,7 +78,7 @@ private void init() { @Named("publicKeyTable") public EntityDbTableInterface getPublicKeyTable() { if (isCacheEnabled()) { - return new CachedTable<>(publicKeyCache, publicKeyTable); + return new CachedTable<>(publicKeyCache, publicKeyTable); } else { return publicKeyTable; } diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/db/JdbiTransactionalInterceptor.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/db/JdbiTransactionalInterceptor.java index 62fa2bd63d..37808dc178 100644 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/db/JdbiTransactionalInterceptor.java +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/db/JdbiTransactionalInterceptor.java @@ -8,6 +8,7 @@ import com.apollocurrency.aplwallet.apl.util.cdi.transaction.JdbiHandleFactory; import org.slf4j.Logger; +import jakarta.annotation.Priority; import jakarta.inject.Inject; import jakarta.interceptor.AroundInvoke; import jakarta.interceptor.Interceptor; @@ -21,6 +22,7 @@ */ @Transactional @Interceptor +@Priority(100) public class JdbiTransactionalInterceptor { private static final Logger log = getLogger(JdbiHandleFactory.class); diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/entity/appdata/BlockIndex.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/entity/appdata/BlockIndex.java index 58ac0438dc..1474aa8f16 100644 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/entity/appdata/BlockIndex.java +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/entity/appdata/BlockIndex.java @@ -1,3 +1,6 @@ +/* + * Copyright © 2019-2021 Apollo Foundation + */ package com.apollocurrency.aplwallet.apl.core.entity.appdata; import lombok.AllArgsConstructor; diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/entity/appdata/PeerEntity.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/entity/appdata/PeerEntity.java new file mode 100644 index 0000000000..b6cb6abf2d --- /dev/null +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/entity/appdata/PeerEntity.java @@ -0,0 +1,39 @@ +/* + * Copyright © 2019-2021 Apollo Foundation + */ +package com.apollocurrency.aplwallet.apl.core.entity.appdata; + +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * DB record of known peer + * + * @author alukin@gmail.com + */ +@Data +@AllArgsConstructor +public class PeerEntity { + + /** + * In previous version address is public IP, but now it could be IP:port or + * 256 bit identity in hexadecimal form + */ + private String address; + /** + * Services of node + */ + private long services; + /** + * time of last update in seconds + */ + private int lastUpdated; + /** + * X.509 certificate of node in PEM format + */ + private String x509pem; + /** + * Last seen on IP and port (IPv4 or IPv6) + */ + private String ipAndPort; +} diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/http/API.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/http/API.java index b46e36f1cd..50a643ff64 100644 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/http/API.java +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/http/API.java @@ -68,7 +68,6 @@ import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher; import org.jboss.resteasy.plugins.server.servlet.ResteasyContextParameters; import org.jboss.weld.environment.servlet.Listener; -import org.slf4j.Logger; import jakarta.inject.Inject; import jakarta.inject.Singleton; @@ -89,8 +88,6 @@ import java.util.Set; import java.util.StringJoiner; -import static org.slf4j.LoggerFactory.getLogger; - @Singleton @Slf4j public final class API { diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/http/JSONData.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/http/JSONData.java index dc105842af..a27fc8b02b 100644 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/http/JSONData.java +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/http/JSONData.java @@ -715,8 +715,8 @@ public static JSONObject peer(Peer peer) { json.put("lastUpdated", peer.getLastUpdated()); json.put("lastConnectAttempt", peer.getLastConnectAttempt()); json.put("inbound", peer.isInbound()); - json.put("inboundWebSocket", peer.isInboundSocket()); - json.put("outboundWebSocket", peer.isOutboundSocket()); + json.put("inboundWebSocket", peer.isInbound()); + json.put("outboundWebSocket", peer.isOutbound()); if (peer.isBlacklisted()) { json.put("blacklistingCause", peer.getBlacklistingCause()); } diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/identity/IdValidator.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/identity/IdValidator.java deleted file mode 100644 index 0c43515a95..0000000000 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/identity/IdValidator.java +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ - -package com.apollocurrency.aplwallet.apl.core.identity; - -/** - * - * @author alukin@gmail.com - */ -public interface IdValidator { - -} diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/identity/IdValidatorImpl.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/identity/IdValidatorImpl.java deleted file mode 100644 index 82b4622273..0000000000 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/identity/IdValidatorImpl.java +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.core.identity; - -/** - * - * @author alukin@gmail.com - */ -public class IdValidatorImpl implements IdValidator{ - -} diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/identity/ThisNodeIdHandler.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/identity/ThisNodeIdHandler.java deleted file mode 100644 index fa2fd5374f..0000000000 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/identity/ThisNodeIdHandler.java +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.core.identity; - -/** - * - * @author alukin@gmail.com - */ -public interface ThisNodeIdHandler { - -} diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/identity/ThisNodeIdHandlerImpl.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/identity/ThisNodeIdHandlerImpl.java deleted file mode 100644 index c7eeea406f..0000000000 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/identity/ThisNodeIdHandlerImpl.java +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.core.identity; - -/** - * - * @author alukin@gmail.com - */ -public class ThisNodeIdHandlerImpl implements ThisNodeIdHandler { - -} diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/GetMorePeersThread.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/GetMorePeersThread.java index 1ffdf3fe8f..5ec424d505 100644 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/GetMorePeersThread.java +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/GetMorePeersThread.java @@ -3,9 +3,11 @@ */ package com.apollocurrency.aplwallet.apl.core.peer; +import com.apollocurrency.aplwallet.apl.core.dao.appdata.PeerDao; import com.apollocurrency.aplwallet.api.p2p.request.AddPeersRequest; import com.apollocurrency.aplwallet.api.p2p.request.GetPeersRequest; import com.apollocurrency.aplwallet.api.p2p.response.GetPeersResponse; +import com.apollocurrency.aplwallet.apl.core.entity.appdata.PeerEntity; import com.apollocurrency.aplwallet.apl.core.peer.parser.GetPeersResponseParser; import com.apollocurrency.aplwallet.apl.core.service.appdata.TimeService; import lombok.extern.slf4j.Slf4j; @@ -30,18 +32,12 @@ class GetMorePeersThread implements Runnable { private final PeersService peersService; private final GetPeersRequest getPeersRequest; private volatile boolean updatedPeer; - private final PeerDb peerDb; - + private final PeerDao peerDao; public GetMorePeersThread(TimeService timeService, PeersService peersService) { this.timeService = timeService; this.peersService = peersService; - this.peerDb = peersService.getPeerDb(); - if (this.peerDb == null) { - String error = "ERROR, the peerDb instance was not initialized inside peerService"; - log.error(error); - throw new RuntimeException(error); - } + this.peerDao = peersService.getPeerDao(); getPeersRequest = new GetPeersRequest(peersService.blockchainConfig.getChain().getChainId()); } @@ -83,7 +79,7 @@ public void run() { } } } - if (PeersService.savePeers && updatedPeer) { + if (peersService.savePeers && updatedPeer) { updateSavedPeers(); updatedPeer = false; } @@ -123,14 +119,14 @@ private void updateSavedPeers() { // // Load the current database entries and map announced address to database entry // - List oldPeers = this.peerDb.loadPeers(); - Map oldMap = new HashMap<>(oldPeers.size()); + List oldPeers = peerDao.loadPeers(); + Map oldMap = new HashMap<>(oldPeers.size()); oldPeers.forEach((entry) -> oldMap.put(entry.getAddress(), entry)); // // Create the current peer map (note that there can be duplicate peer entries with // the same announced address) // - Map currentPeers = new HashMap<>(); + Map currentPeers = new HashMap<>(); UUID chainId = peersService.blockchainConfig.getChain().getChainId(); peersService.getPeers( peer -> peer.getAnnouncedAddress() != null @@ -138,20 +134,20 @@ private void updateSavedPeers() { && chainId.equals(peer.getChainId()) && now - peer.getLastUpdated() < 7 * 24 * 3600 ).forEach((peer) -> { - currentPeers.put(peer.getAnnouncedAddress(), new PeerDb.Entry(peer.getAnnouncedAddress(), peer.getServices(), peer.getLastUpdated())); + currentPeers.put(peer.getIdentity(), new PeerEntity(peer.getAnnouncedAddress(), peer.getServices(), peer.getLastUpdated(),peer.getX509pem(),peer.getHostWithPort())); }); // // Build toDelete and toUpdate lists // - List toDelete = new ArrayList<>(oldPeers.size()); + List toDelete = new ArrayList<>(oldPeers.size()); oldPeers.forEach((entry) -> { if (currentPeers.get(entry.getAddress()) == null) { toDelete.add(entry); } }); - List toUpdate = new ArrayList<>(currentPeers.size()); + List toUpdate = new ArrayList<>(currentPeers.size()); currentPeers.values().forEach((entry) -> { - PeerDb.Entry oldEntry = oldMap.get(entry.getAddress()); + PeerEntity oldEntry = oldMap.get(entry.getAddress()); if (oldEntry == null || entry.getLastUpdated() - oldEntry.getLastUpdated() > 24 * 3600) { toUpdate.add(entry); } @@ -167,8 +163,8 @@ private void updateSavedPeers() { // try { - this.peerDb.deletePeers(toDelete); - this.peerDb.updatePeers(toUpdate); + peerDao.deletePeers(toDelete); + peerDao.updatePeers(toUpdate); } catch (Exception e) { throw e; } diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/Peer.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/Peer.java index 63651773ec..88161fad52 100644 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/Peer.java +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/Peer.java @@ -15,7 +15,7 @@ */ /* - * Copyright © 2018 Apollo Foundation + * Copyright © 2018-2021 Apollo Foundation */ package com.apollocurrency.aplwallet.apl.core.peer; @@ -31,6 +31,14 @@ import java.util.UUID; public interface Peer extends Comparable { + /** max time difference allowed between this and remote node to + * check siganture of epoch time + */ + int MAX_TIME_DIFF = 2; + /** + * @return ID of peer. It is UID field of X.509 certificate + */ + String getIdentity(); boolean providesService(Service service); @@ -44,6 +52,8 @@ public interface Peer extends Comparable { String getAnnouncedAddress(); + void setAnnouncedAddress(String addr); + PeerState getState(); Version getVersion(); @@ -94,10 +104,6 @@ public interface Peer extends Comparable { boolean isOutbound(); - boolean isInboundSocket(); - - boolean isOutboundSocket(); - boolean isOpenAPI(); boolean isApiConnectable(); @@ -116,8 +122,6 @@ public interface Peer extends Comparable { T send(BaseP2PRequest request, JsonReqRespParser parser) throws PeerNotConnectedException; - boolean isTrusted(); - PeerTrustLevel getTrustLevel(); void sendAsync(BaseP2PRequest request); @@ -134,6 +138,8 @@ public interface Peer extends Comparable { void setLastUpdated(int time); + String getX509pem(); + enum Service { HALLMARK(1), // Hallmarked node PRUNABLE(2), // Stores expired prunable messages diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerAddress.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerAddress.java index 0831ee10f4..56727b8779 100644 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerAddress.java +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerAddress.java @@ -115,7 +115,21 @@ public boolean isLocal() { || ipAddress.isLinkLocalAddress()); return res; } - + + public boolean isPublic(){ + boolean not_public = + ipAddress.isLinkLocalAddress() + || ipAddress.isLoopbackAddress() + || ipAddress.isSiteLocalAddress() // 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 + || ipAddress.isAnyLocalAddress() + || ipAddress.isMulticastAddress(); + return ! not_public; + } + + public boolean isValid() { + return valid; + } + @Override public int compareTo(Object t) { int res = -1; @@ -131,13 +145,10 @@ public int compareTo(Object t) { return res; } - public boolean isValid() { - return valid; - } + @Override public String toString() { return "host:" + ipAddress + " name:" + hostName + " port: " + port; } - } diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerConnectingThread.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerConnectingThread.java index 6c8a1d438b..9c86a042f2 100644 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerConnectingThread.java +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerConnectingThread.java @@ -90,7 +90,7 @@ public void run() { && PeersService.enableHallmarkProtection && peer.getWeight() == 0 && peersService.hasTooManyOutboundConnections()) { - LOG.debug("Too many outbound connections, deactivating peer {}", peer.getHost()); + LOG.debug("Too many outbound connections, deactivating peer {}", peer.getHostWithPort()); peer.deactivate("Too many outbound connections"); } return null; diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerHttpServer.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerHttpServer.java index 095470d01c..9ab976473c 100644 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerHttpServer.java +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerHttpServer.java @@ -36,6 +36,7 @@ import java.util.EnumSet; import java.util.List; import java.util.stream.Collectors; +import lombok.Getter; import static org.slf4j.LoggerFactory.getLogger; @@ -61,15 +62,20 @@ public class PeerHttpServer { private final int idleTimeout; boolean shareMyAddress = false; boolean enablePeerUPnP; - private int myPeerServerPort; + private final int myPeerServerPort; private PeerAddress myExtAddress; private PeerServlet peerServlet; - private TaskDispatchManager taskDispatchManager; - private List p2pPortHolders = new ArrayList<>(); + private final TaskDispatchManager taskDispatchManager; + private final List p2pPortHolders = new ArrayList<>(); private WebSocketComponents components; @Inject - public PeerHttpServer(PropertiesHolder propertiesHolder, UPnP upnp, JettyConnectorCreator conCreator, TaskDispatchManager taskDispatchManager) { + public PeerHttpServer( + PropertiesHolder propertiesHolder, UPnP upnp, + JettyConnectorCreator conCreator, + TaskDispatchManager taskDispatchManager + ) + { this.upnp = upnp; this.taskDispatchManager = taskDispatchManager; shareMyAddress = propertiesHolder.getBooleanProperty("apl.shareMyAddress") && !propertiesHolder.isOffline(); @@ -81,6 +87,7 @@ public PeerHttpServer(PropertiesHolder propertiesHolder, UPnP upnp, JettyConnect if (platform.length() > MAX_PLATFORM_LENGTH) { platform = platform.substring(0, MAX_PLATFORM_LENGTH); } + myPlatform = platform; enablePeerUPnP = propertiesHolder.getBooleanProperty("apl.enablePeerUPnP"); diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerImpl.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerImpl.java index 2251365172..52c0827eed 100644 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerImpl.java +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerImpl.java @@ -34,6 +34,7 @@ import com.apollocurrency.aplwallet.apl.core.service.blockchain.BlockchainProcessor; import com.apollocurrency.aplwallet.apl.core.service.state.account.AccountService; import com.apollocurrency.aplwallet.apl.crypto.Convert; +import com.apollocurrency.aplwallet.apl.security.id.IdentityService; import com.apollocurrency.aplwallet.apl.util.Constants; import com.apollocurrency.aplwallet.apl.util.StringUtils; import com.apollocurrency.aplwallet.apl.util.Version; @@ -43,17 +44,26 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule; import com.google.common.util.concurrent.TimeLimiter; +import io.firstbridge.identity.cert.ActorType; +import io.firstbridge.identity.cert.CertException; +import io.firstbridge.identity.cert.CertKeyPersistence; +import io.firstbridge.identity.cert.ExtCert; +import io.firstbridge.identity.handler.IdValidator; +import io.firstbridge.identity.utils.Hex; import lombok.Getter; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.json.simple.JSONObject; import org.json.simple.JSONStreamAware; import org.json.simple.JSONValue; import org.json.simple.parser.ParseException; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.StringWriter; import java.net.InetAddress; import java.net.UnknownHostException; +import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; import java.sql.SQLException; import java.util.ArrayList; @@ -71,8 +81,12 @@ import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import static java.lang.Math.abs; + @Slf4j public final class PeerImpl implements Peer { + + @Getter public static final String CAN_NOT_DESERIALIZE_REQUEST_MSG = "Can not deserialize request"; private final String host; @@ -84,31 +98,43 @@ public final class PeerImpl implements Peer { private final Blockchain blockchain; private final PeersService peers; private final AccountService accountService; + @Getter private final PeerInfo pi = new PeerInfo(); //Jackson JSON private final ObjectMapper mapper = new ObjectMapper(); @Getter private final Peer2PeerTransport p2pTransport; + @Getter private volatile int port; + @Getter private Hallmark hallmark; private EnumSet disabledAPIs; + @Getter private Version version; private volatile boolean isOldVersion; private volatile long adjustedWeight; private volatile int blacklistingTime; - private volatile String blacklistingCause; + @Getter + private volatile String blacklistingCause = "unknown"; + @Getter private PeerState state; + @Getter @Setter private volatile int lastUpdated; + @Getter private volatile int lastConnectAttempt; private volatile long hallmarkBalance = -1; private volatile int hallmarkBalanceHeight; private volatile long services; + @Getter private BlockchainState blockchainState; - private TimeService timeService; + private final TimeService timeService; @Getter private volatile int failedConnectAttempts = 0; + private String peerId; + @Getter + private PeerTrustLevel trustLevel = PeerTrustLevel.NOT_TRUSTED; private volatile ThreadPoolExecutor asyncExecutor; - + private final IdentityService identityService; PeerImpl(PeerAddress addrByFact, PeerAddress announcedAddress, BlockchainConfig blockchainConfig, @@ -117,7 +143,8 @@ public final class PeerImpl implements Peer { PeerServlet peerServlet, PeersService peers, TimeLimiter timeLimiter, - AccountService accountService + AccountService accountService, + IdentityService identityService ) { //TODO: remove Json.org entirely from P2P mapper.registerModule(new JsonOrgModule()); @@ -142,15 +169,11 @@ public final class PeerImpl implements Peer { this.p2pTransport = new Peer2PeerTransport(this, peerServlet, timeLimiter); state = PeerState.NON_CONNECTED; // set this peer its' initial state this.accountService = accountService; + this.identityService = identityService; } private void initAsyncExecutor() { - this.asyncExecutor = new TimeTraceDecoratedThreadPoolExecutor(1, Math.max(Runtime.getRuntime().availableProcessors() / 2, 1), 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1000), new NamedThreadFactory(getHost() + "-AsyncExecutor")); - } - - @Override - public String getHost() { - return host; + this.asyncExecutor = new TimeTraceDecoratedThreadPoolExecutor(1, Math.max(Runtime.getRuntime().availableProcessors() / 2, 1), 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1000), new NamedThreadFactory(getHostWithPort()+ "-AsyncExecutor")); } @Override @@ -159,10 +182,6 @@ public String getHostWithPort() { return pa.getAddrWithPort(); } - @Override - public PeerState getState() { - return state; - } private void setState(PeerState newState) { // if we are even not connected and some routine say to disconnect @@ -209,11 +228,6 @@ public long getUploadedVolume() { return p2pTransport.getUploadedVolume(); } - @Override - public Version getVersion() { - return version; - } - public void setVersion(Version version) { boolean versionChanged = version == null || !version.equals(this.version); this.version = version; @@ -320,10 +334,6 @@ public void setApiServerIdleTimeout(Integer apiServerIdleTimeout) { pi.setApiServerIdleTimeout(apiServerIdleTimeout); } - @Override - public BlockchainState getBlockchainState() { - return blockchainState; - } public void setBlockchainState(Integer blockchainStateInt) { if (blockchainStateInt >= 0 && blockchainStateInt < BlockchainState.values().length) { @@ -351,7 +361,8 @@ public String getAnnouncedAddress() { * * @param announcedAddress address with port optionally */ - void setAnnouncedAddress(String announcedAddress) { + @Override + public void setAnnouncedAddress(String announcedAddress) { if (announcedAddress != null && announcedAddress.length() > PeersService.MAX_ANNOUNCED_ADDRESS_LENGTH) { throw new IllegalArgumentException("Announced address too long: " + announcedAddress.length()); } @@ -360,15 +371,6 @@ void setAnnouncedAddress(String announcedAddress) { this.port = pa.getPort(); } - @Override - public int getPort() { - return port; - } - - @Override - public Hallmark getHallmark() { - return hallmark; - } private void setHallmark(Hallmark hallmark) { this.hallmark = hallmark; @@ -463,46 +465,16 @@ public void remove() { peers.notifyListeners(this, PeersService.Event.REMOVE); } - @Override - public int getLastUpdated() { - return lastUpdated; - } - - @Override - public void setLastUpdated(int lastUpdated) { - this.lastUpdated = lastUpdated; - } - @Override public boolean isInbound() { - return pi.getAnnouncedAddress() == null; - } - - @Override - public boolean isOutbound() { - return pi.getAnnouncedAddress() != null; - } - - @Override - public boolean isInboundSocket() { return p2pTransport.isInbound(); } @Override - public boolean isOutboundSocket() { + public boolean isOutbound() { return p2pTransport.isOutbound(); } - @Override - public String getBlacklistingCause() { - return blacklistingCause == null ? "unknown" : blacklistingCause; - } - - @Override - public int getLastConnectAttempt() { - return lastConnectAttempt; - } - @Override public long getLastActivityTime() { return p2pTransport.getLastActivity(); @@ -693,14 +665,14 @@ public synchronized boolean handshake() { if (!setApplication(newPi.getApplication())) { log.trace("Peer: {} has different Application value '{}', removing", - getHost(), newPi.getApplication()); + getHostWithPort(), newPi.getApplication()); remove(); return false; } if (newPi.getChainId() == null || !targetChainId.equals(UUID.fromString(newPi.getChainId()))) { log.trace("Peer: {} has different chainId: '{}', removing", - getHost(), newPi.getChainId()); + getHostWithPort(), newPi.getChainId()); remove(); return false; } @@ -732,6 +704,7 @@ public synchronized boolean handshake() { setPlatform(newPi.getPlatform()); setShareAddress(newPi.getShareAddress()); + setX509pem(newPi); if (!PeersService.ignorePeerAnnouncedAddress) { if (newPi.getAnnouncedAddress() != null && newPi.getShareAddress()) { @@ -963,43 +936,6 @@ public StringBuilder getPeerApiUri() { return uri; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - PeerImpl peer = (PeerImpl) o; - return port == peer.port && - Objects.equals(host, peer.host) && - Objects.equals(pi.getAnnouncedAddress(), peer.getAnnouncedAddress()); - } - - @Override - public int hashCode() { - return Objects.hash(host, pi.getAnnouncedAddress(), port); - } - - @Override - public String toString() { - return "Peer{" + - "state=" + getState() + - ", announcedAddress='" + pi.getAnnouncedAddress() + '\'' + - ", services=" + services + - ", host='" + host + '\'' + - ", application ='" + getApplication() + '\'' + - ", version='" + version + '\'' + - '}'; - } - - @Override - public boolean isTrusted() { - return getTrustLevel().getCode() > PeerTrustLevel.REGISTERED.getCode(); - } - - @Override - public PeerTrustLevel getTrustLevel() { - //TODO implement using Apollo ID - return PeerTrustLevel.NOT_TRUSTED; - } /** * process error from transport and application level @@ -1047,4 +983,102 @@ public boolean processError(JSONObject message) { } } +//--------- X.509 certificates related methods + @Override + public String getX509pem() { + return pi.getX509_cert(); + } + + public void setX509pem(PeerInfo pi) { + String pem = pi.getX509_cert(); + + if (pem == null || pem.isEmpty()) { + return; + } + try { + ExtCert xc = CertKeyPersistence.loadCertPEMFromStream(new ByteArrayInputStream(pem.getBytes())); + if (xc == null) { + log.debug("Error reading certificate of peer: {}", getHostWithPort()); + return; + } + + IdValidator idValidator = identityService.getPeerIdValidator(); + //we should verify private key ownership by checking the signature of timestamp + ByteBuffer bb = ByteBuffer.allocate(Integer.SIZE); + bb.putInt(pi.getBlockTime()); + byte[] data = bb.array(); + byte[] signature = Hex.decode(pi.getEpochTimeSigantureHex()); + + boolean signatureValid = identityService.getPeerIdValidator().verifySignedData(xc.getCertificate(), data, signature); + + boolean timeDiffValid = abs(timeService.getEpochTime() - pi.getEpochTime()) <= MAX_TIME_DIFF; + + if (!timeDiffValid) { + log.warn("Time difference exceeds max allowed value for node {}", getHostWithPort()); + return; + } + if (signatureValid) { + log.debug("Ignoring self-signed certificate because timestamp signature is wrong for peer: {}", getHostWithPort()); + return; + } + + peerId = Hex.encode(xc.getActorId()); + if (xc.isSelfSigned()) { + trustLevel = PeerTrustLevel.REGISTERED; + } else if (idValidator.isTrusted(xc.getCertificate())) { + trustLevel = PeerTrustLevel.TRUSTED; + if ((xc.getAuthorityId().getActorType().getType() & ActorType.NODE_CERTIFIED_STORAGE) != 0) { + trustLevel = PeerTrustLevel.SYSTEM_TRUSTED; + } + } else { + log.debug("Can not determine trust level of peer certificate, signed by unknown CA for peer: {}", getHostWithPort()); + } + } catch (IOException | CertException ex) { + log.debug("Can not read certificate of peer: {}", getHostWithPort()); + } + } + + @Override + public String getIdentity() { + String res; + if (peerId!=null){ + res = peerId; + }else{ + res = getHostWithPort(); + } + return res; + } + +//----------- overwitten methods of Object + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PeerImpl peer = (PeerImpl) o; + return port == peer.port && + Objects.equals(host, peer.host) && + Objects.equals(pi.getAnnouncedAddress(), peer.getAnnouncedAddress()); + } + + @Override + public int hashCode() { + return Objects.hash(host, pi.getAnnouncedAddress(), port); + } + + @Override + public String toString() { + return "Peer{" + + "state=" + getState() + + ", announcedAddress='" + pi.getAnnouncedAddress() + '\'' + + ", services=" + services + + ", host='" + host + '\'' + + ", application ='" + getApplication() + '\'' + + ", version='" + version + '\'' + + '}'; + } + + @Override + public String getHost() { + return host; + } } diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerLoaderThread.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerLoaderThread.java index 80e422ecb1..ca982fde6a 100644 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerLoaderThread.java +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeerLoaderThread.java @@ -3,6 +3,8 @@ */ package com.apollocurrency.aplwallet.apl.core.peer; +import com.apollocurrency.aplwallet.apl.core.dao.appdata.PeerDao; +import com.apollocurrency.aplwallet.apl.core.entity.appdata.PeerEntity; import com.apollocurrency.aplwallet.apl.core.service.appdata.TimeService; import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; @@ -21,10 +23,11 @@ class PeerLoaderThread implements Runnable { private static final Logger LOG = LoggerFactory.getLogger(PeerLoaderThread.class); private final List defaultPeers; private final List> unresolvedPeers; - private final Set entries = new HashSet<>(); + private final Set entries = new HashSet<>(); private final TimeService timeService; private final PeersService peersService; - private final PeerDb peerDb; + + private PeerDao peerDao; public PeerLoaderThread(List defaultPeers, List> unresolvedPeers, @@ -33,32 +36,32 @@ public PeerLoaderThread(List defaultPeers, this.defaultPeers = defaultPeers; this.unresolvedPeers = unresolvedPeers; this.timeService = timeService; - this.peersService = peersService; - this.peerDb = peersService.getPeerDb(); + this.peersService = peersService; } @Override public void run() { LOG.trace("'Peer loader': thread starting..."); - if (this.peerDb == null) { -// peerDb = CDI.current().select(PeerDb.class).get(); - String error = "ERROR, the peerDb instance was not initialized inside peerService"; - log.error(error); - throw new RuntimeException(error); + if (peerDao == null) { + peerDao = peersService.getPeerDao(); } final int now = timeService.getEpochTime(); + //TODO: add enties after connection established and x.509 is known peersService.wellKnownPeers.forEach((address) -> { PeerAddress pa = new PeerAddress(address); - entries.add(new PeerDb.Entry(pa.getAddrWithPort(), 0, now)); + entries.add(new PeerEntity(pa.getAddrWithPort(), 0, now,null,pa.getAddrWithPort())); }); - if (PeersService.usePeersDb) { + + //TODO: re-define default peers + if (peersService.usePeersDb) { LOG.debug("'Peer loader': Loading 'well known' peers from the database..."); defaultPeers.forEach((address) -> { PeerAddress pa = new PeerAddress(address); - entries.add(new PeerDb.Entry(pa.getAddrWithPort(), 0, now)); + entries.add(new PeerEntity(pa.getAddrWithPort(), 0, now, null, pa.getAddrWithPort())); }); - if (PeersService.savePeers) { - List dbPeers = peerDb.loadPeers(); + + if (peersService.savePeers) { + List dbPeers = peerDao.loadPeers(); dbPeers.forEach((entry) -> { if (!entries.add(entry)) { // Database entries override entries from chains.json @@ -69,6 +72,7 @@ public void run() { }); } } + if (!entries.isEmpty()) { LOG.debug("'Peer loader': findOrCreatePeer() 'known peers'..."); } diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeersService.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeersService.java index de3fbeac74..9ab7a7a017 100644 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeersService.java +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/PeersService.java @@ -28,6 +28,8 @@ import com.apollocurrency.aplwallet.apl.core.model.Block; import com.apollocurrency.aplwallet.apl.core.model.Transaction; import com.apollocurrency.aplwallet.apl.core.chainid.BlockchainConfig; +import com.apollocurrency.aplwallet.apl.core.dao.appdata.PeerDao; +import com.apollocurrency.aplwallet.apl.core.entity.appdata.PeerEntity; import com.apollocurrency.aplwallet.apl.core.http.API; import com.apollocurrency.aplwallet.apl.core.http.APIEnum; import com.apollocurrency.aplwallet.apl.core.rest.converter.BlockConverter; @@ -39,6 +41,7 @@ import com.apollocurrency.aplwallet.apl.core.service.blockchain.BlockchainProcessor; import com.apollocurrency.aplwallet.apl.core.service.state.account.AccountService; import com.apollocurrency.aplwallet.apl.crypto.Convert; +import com.apollocurrency.aplwallet.apl.security.id.IdentityService; import com.apollocurrency.aplwallet.apl.util.Constants; import com.apollocurrency.aplwallet.apl.util.Filter; import com.apollocurrency.aplwallet.apl.util.JSON; @@ -56,6 +59,8 @@ import com.apollocurrency.aplwallet.apl.util.task.Tasks; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule; +import io.firstbridge.identity.cert.ExtCert; +import io.firstbridge.identity.utils.Hex; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.json.simple.JSONObject; @@ -66,6 +71,7 @@ import jakarta.enterprise.inject.spi.CDI; import jakarta.inject.Inject; import jakarta.inject.Singleton; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -98,7 +104,7 @@ public class PeersService { private static final Version MAX_VERSION = Constants.VERSION; private static final int sendTransactionsBatchSize = 200; private final static String BACKGROUND_SERVICE_NAME = "PeersService"; - public static int DEFAULT_CONNECT_TIMEOUT = 2000; //2s default websocket connect timeout + public static final int DEFAULT_CONNECT_TIMEOUT = 2000; //2s default websocket connect timeout public static int connectTimeout = DEFAULT_CONNECT_TIMEOUT; public static boolean getMorePeers; //TODO: hardcode in Constants and use from there @@ -118,8 +124,8 @@ public class PeersService { static boolean isGzipEnabled; static int minNumberOfKnownPeers; static boolean enableHallmarkProtection; - static boolean usePeersDb; - static boolean savePeers; + boolean usePeersDb; + boolean savePeers; static boolean cjdnsOnly; private static String myHallmark; private static int maxNumberOfInboundConnections; @@ -128,7 +134,6 @@ public class PeersService { private static int pushThreshold; private static int pullThreshold; private static int sendToPeersLimit; - private static volatile JSONObject myPeerInfo; public final ExecutorService peersExecutorService = new QueuedThreadPool(2, 15, "PeersExecutorService"); public final boolean isLightClient; @Getter @@ -163,9 +168,13 @@ public class PeersService { private BlockchainProcessor blockchainProcessor; private final TimeService timeService; private final UnconfirmedTransactionConverter transactionConverter; + private final IdentityService identityService; + @Getter + private final PeerDao peerDao; private final BlockConverter blockConverter; + private ObjectMapper mapper; + // private final ExecutorService txSendingDispatcher; - private final PeerDb peerDb; @Inject public PeersService(PropertiesHolder propertiesHolder, @@ -178,7 +187,8 @@ public PeersService(PropertiesHolder propertiesHolder, AccountService accountService, UnconfirmedTransactionConverterCreator txConverterCreator, BlockConverterCreator blockConverterCreator, - PeerDb peerDb) { + IdentityService identityService, + PeerDao peerDao) { this.propertiesHolder = propertiesHolder; this.blockchainConfig = blockchainConfig; this.blockchain = blockchain; @@ -187,14 +197,22 @@ public PeersService(PropertiesHolder propertiesHolder, this.peerHttpServer = peerHttpServer; this.timeLimiterService = timeLimiterService; this.accountService = accountService; - this.transactionConverter = txConverterCreator.create(false); + this.identityService = identityService; + this.peerDao = peerDao; this.blockConverter = blockConverterCreator.create(true, false, false); - this.peerDb = peerDb; + this.transactionConverter = txConverterCreator.create(false); +// this.transactionConverter.setPriv(false); +// this.blockConverter.setPriv(false); +// this.blockConverter.setAddTransactions(true); int asyncTxSendingPoolSize = propertiesHolder.getIntProperty("apl.maxAsyncPeerSendingPoolSize", 30); // this.txSendingDispatcher = new ThreadPoolExecutor(5, asyncTxSendingPoolSize, 10_000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(asyncTxSendingPoolSize), new NamedThreadFactory("P2PTxSendingPool", true)); this.sendingService = new TimeTraceDecoratedThreadPoolExecutor(10, asyncTxSendingPoolSize, 10_000, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>(1000), new NamedThreadFactory("PeersSendingService")); isLightClient = propertiesHolder.isLightClient(); + //configure object mapper for PeerInfo + mapper = new ObjectMapper(); + mapper.registerModule(new JsonOrgModule()); + } private BlockchainProcessor lookupBlockchainProcessor() { @@ -282,27 +300,26 @@ public void init() { LOG.info("Using a proxy, will not create outbound websockets."); } - fillMyPeerInfo(); + //NodeID feature + if(!identityService.loadMyIdentity()){ + log.error("Can not load or generate this node identity certificate or key"); + } + + if(!identityService.loadTrustedCaCerts()){ + log.error("Can not load trusted CA certificates, node ID verification is impossible"); + } addListener(peer -> peersExecutorService.submit(() -> { if (peer.getAnnouncedAddress() != null && !peer.isBlacklisted()) { try { - this.peerDb.updatePeer((PeerImpl) peer); + peerDao.updatePeer(peer); } catch (RuntimeException e) { LOG.error("Unable to update peer database", e); } } }), PeersService.Event.CHANGED_SERVICES); - // moved to Weld Event - /* Account.addListener(account -> connectablePeers.values().forEach(peer -> { - if (peer.getHallmark() != null && peer.getHallmark().getAccountId() == account.getId()) { - listeners.notify(peer, Event.WEIGHT); - } - }), AccountEventType.BALANCE);*/ - configureBackgroundTasks(); - peerHttpServer.start(); } @@ -346,8 +363,8 @@ private void configureBackgroundTasks() { } } - private void fillMyPeerInfo() { - myPeerInfo = new JSONObject(); + private JSONObject fillMyPeerInfo() { + JSONObject myPeerInfo = new JSONObject(); PeerInfo pi = new PeerInfo(); LOG.debug("Start filling 'MyPeerInfo'..."); List servicesList = new ArrayList<>(); @@ -419,12 +436,22 @@ private void fillMyPeerInfo() { pi.setServices(Long.toUnsignedString(services)); myServices = Collections.unmodifiableList(servicesList); - ObjectMapper mapper = new ObjectMapper(); - mapper.registerModule(new JsonOrgModule()); + ExtCert myId = identityService.getThisNodeIdHandler().getExtCert(); + if(myId!=null){ + pi.setX509_cert(myId.getCertPEM()); + } +//NodeId feature + pi.setEpochTime(timeService.getEpochTime()); + ByteBuffer bb = ByteBuffer.allocate(Integer.SIZE); + bb.putInt(pi.getEpochTime()); + byte[] signature = identityService.getThisNodeIdHandler().sign(bb.array()); + pi.setEpochTimeSigantureHex(Hex.encode(signature)); + myPeerInfo = mapper.convertValue(pi, JSONObject.class); - LOG.debug("My peer info:\n" + myPeerInfo.toJSONString()); + LOG.trace("My peer info:\n" + myPeerInfo.toJSONString()); myPI = pi; - LOG.debug("Finished filling 'MyPeerInfo'"); + LOG.trace("Finished filling 'MyPeerInfo'"); + return myPeerInfo; } public PeerInfo getMyPeerInfo() { @@ -624,7 +651,7 @@ public Peer findOrCreatePeer(PeerAddress actualAddr, final String announcedAddre //if it is not resolvable PeerAddress apa = resolveAnnouncedAddress(announcedAddress); peer = new PeerImpl(actualAddr, apa, blockchainConfig, blockchain, timeService, peerHttpServer.getPeerServlet(), - this, timeLimiterService.acquireLimiter("P2PTransport"), accountService); + this, timeLimiterService.acquireLimiter("P2PTransport"), accountService, identityService); listeners.notify(peer, Event.NEW_PEER); if (apa != null) { connectablePeers.put(apa.getAddrWithPort(), peer); @@ -634,13 +661,14 @@ public Peer findOrCreatePeer(PeerAddress actualAddr, final String announcedAddre return peer; } - public void setAnnouncedAddress(PeerImpl peer, String newAnnouncedAddress) { + public boolean setAnnouncedAddress(Peer peer, String newAnnouncedAddress) { if (StringUtils.isBlank(newAnnouncedAddress)) { LOG.debug("newAnnouncedAddress is empty for host: {}, ignoring", peer.getHostWithPort()); } PeerAddress newPa = resolveAnnouncedAddress(newAnnouncedAddress); - if (newPa == null) { - return; + if (newPa == null || !newPa.isPublic()) { + log.debug("Peer {} announced wrong or not public address: {}", peer.getHostWithPort(), newAnnouncedAddress); + return false; } String oldAnnouncedAddr = peer.getAnnouncedAddress(); Peer oldPeer = null; @@ -652,17 +680,20 @@ public void setAnnouncedAddress(PeerImpl peer, String newAnnouncedAddress) { if (newPa.compareTo(oldPa) != 0) { LOG.debug("Removing old announced address {} for peer {}:{}", oldPa, oldPeer.getHost(), oldPeer.getPort()); - peer.setAnnouncedAddress(newAnnouncedAddress); + peer.setAnnouncedAddress(newPa.getAddrWithPort()); oldPeer = removePeer(oldPeer); if (oldPeer != null) { notifyListeners(oldPeer, Event.REMOVE); } } } + return true; } - public boolean addPeer(Peer peer, String newAnnouncedAddress) { - setAnnouncedAddress((PeerImpl) peer, newAnnouncedAddress.toLowerCase()); + public boolean addPeer(Peer peer, String announcedAddress) { + if(setAnnouncedAddress(peer, announcedAddress.toLowerCase())){ + return false; + } return addPeer(peer); } @@ -670,7 +701,7 @@ public boolean addPeer(Peer peer) { if (peer != null && peer.getAnnouncedAddress() != null) { // put new or replace previous - connectablePeers.put(peer.getAnnouncedAddress(), peer); + connectablePeers.put(peer.getAnnouncedAddress(), peer); listeners.notify(peer, Event.NEW_PEER); return true; } @@ -701,8 +732,10 @@ void cleanupPeers(Peer peer) { public Peer removePeer(Peer peer) { Peer p = null; if (peer.getAnnouncedAddress() != null) { - PeerDb.Entry entry = new PeerDb.Entry(peer.getAnnouncedAddress(), 0, 0); - this.peerDb.deletePeer(entry); + + PeerEntity entry = new PeerEntity(peer.getIdentity(), 0, 0,null,peer.getHostWithPort()); + peerDao.deletePeer(entry); + if (connectablePeers.containsKey(peer.getAnnouncedAddress())) { p = connectablePeers.remove(peer.getAnnouncedAddress()); } @@ -912,8 +945,9 @@ private void checkBlockchainState() { ? BlockchainState.FORK : BlockchainState.UP_TO_DATE; if (state != currentBlockchainState) { - JSONObject json = new JSONObject(myPeerInfo); + JSONObject json = new JSONObject(fillMyPeerInfo()); json.put("blockchainState", state.ordinal()); + myPeerInfoResponse = JSON.prepare(json); json.put("requestType", "getInfo"); myPeerInfoRequest = JSON.prepareRequest(json); @@ -936,8 +970,8 @@ public BlockchainState getMyBlockchainState() { return currentBlockchainState; } - public PeerDb getPeerDb() { - return peerDb; + public PeerDao getPeerDb() { + return peerDao; } public enum Event { diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/endpoint/GetInfo.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/endpoint/GetInfo.java index 820aaaed92..55154b2c54 100644 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/endpoint/GetInfo.java +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/peer/endpoint/GetInfo.java @@ -21,17 +21,16 @@ package com.apollocurrency.aplwallet.apl.core.peer.endpoint; import com.apollocurrency.aplwallet.api.p2p.PeerInfo; -import com.apollocurrency.aplwallet.apl.core.service.appdata.TimeService; import com.apollocurrency.aplwallet.apl.core.peer.Peer; import com.apollocurrency.aplwallet.apl.core.peer.PeerImpl; import com.apollocurrency.aplwallet.apl.core.peer.PeersService; +import com.apollocurrency.aplwallet.apl.core.service.appdata.TimeService; import com.apollocurrency.aplwallet.apl.crypto.Convert; import com.apollocurrency.aplwallet.apl.util.JSON; import com.apollocurrency.aplwallet.apl.util.Version; +import lombok.extern.slf4j.Slf4j; import org.json.simple.JSONObject; import org.json.simple.JSONStreamAware; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import jakarta.inject.Inject; import jakarta.inject.Singleton; @@ -39,8 +38,8 @@ import java.io.StringWriter; @Singleton +@Slf4j public class GetInfo extends PeerRequestHandler { - private static final Logger log = LoggerFactory.getLogger(GetInfo.class); private static final JSONStreamAware INVALID_ANNOUNCED_ADDRESS; private static final JSONStreamAware INVALID_APPLICATION; private static final JSONStreamAware INVALID_CHAINID; @@ -66,11 +65,14 @@ public GetInfo(TimeService timeService) { this.timeService = timeService; } + @Override public JSONStreamAware processRequest(JSONObject req, Peer peer) { PeerImpl peerImpl = (PeerImpl) peer; PeerInfo pi = mapper.convertValue(req, PeerInfo.class); log.trace("GetInfo - PeerInfo from request = {}", pi); + + peerImpl.setX509pem(pi); peerImpl.setLastUpdated(timeService.getEpochTime()); long origServices = peerImpl.getServices(); String servicesString = pi.getServices(); @@ -83,17 +85,16 @@ public JSONStreamAware processRequest(JSONObject req, Peer peer) { announcedAddress = announcedAddress.toLowerCase(); if (announcedAddress != null) { if (!peerImpl.verifyAnnouncedAddress(announcedAddress)) { - log.trace("GetInfo: ignoring invalid announced address for " + peerImpl.getHost()); + log.trace("GetInfo: ignoring invalid announced address for {}", peerImpl.getHostWithPort()); if (!peerImpl.verifyAnnouncedAddress(peerImpl.getAnnouncedAddress())) { - log.trace("GetInfo: old announced address for " + peerImpl.getHost() + " no longer valid"); + log.trace("GetInfo: old announced address for {} no longer valid", peerImpl.getHostWithPort()); lookupPeersService().setAnnouncedAddress(peerImpl, null); } peer.deactivate("Invalid announced address: " + announcedAddress); return INVALID_ANNOUNCED_ADDRESS; } if (!announcedAddress.equals(peerImpl.getAnnouncedAddress())) { - log.trace("GetInfo: peer " + peer.getHost() + " changed announced address from " + peer.getAnnouncedAddress() + " to " + announcedAddress); - int oldPort = peerImpl.getPort(); + log.trace("GetInfo: peer {} changed announced address from {} to {}", peer.getHost(), peer.getAnnouncedAddress(), announcedAddress); lookupPeersService().setAnnouncedAddress(peerImpl, announcedAddress); } } else { @@ -103,7 +104,7 @@ public JSONStreamAware processRequest(JSONObject req, Peer peer) { } if (!peerImpl.setApplication(pi.getApplication().trim())) { - log.trace("Invalid application. IP: {}, application value: '{}', removing", peerImpl.getHost(), pi.getApplication()); + log.trace("Invalid application. IP: {}, application value: '{}', removing", peerImpl.getHostWithPort(), pi.getApplication()); // log.debug("Peer = {} Received Invalid App in PI = \n{}", peerImpl, pi); peerImpl.remove(); return INVALID_APPLICATION; @@ -121,7 +122,7 @@ public JSONStreamAware processRequest(JSONObject req, Peer peer) { log.error("Cannot parse version = '{}'", pi.getVersion(), e); version = new Version(1, 0, 0); } - log.trace("PEER-GetINFO: IP: {}, application: {} version {}", peerImpl.getHost(), pi.getApplication(), version); + log.trace("PEER-GetINFO: IP: {}, application: {} version {}", peerImpl.getHostWithPort(), pi.getApplication(), version); peerImpl.setVersion(version); if (pi.getPlatform() == null) { diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/rest/converter/PeerConverter.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/rest/converter/PeerConverter.java index a77a429d7d..d822e8340e 100644 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/rest/converter/PeerConverter.java +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/rest/converter/PeerConverter.java @@ -40,8 +40,8 @@ public PeerDTO apply(Peer peer) { dto.setLastUpdated(peer.getLastUpdated()); dto.setLastConnectAttempt(peer.getLastConnectAttempt()); dto.setInbound(peer.isInbound()); - dto.setInboundWebSocket(peer.isInboundSocket()); - dto.setOutboundWebSocket(peer.isOutboundSocket()); + dto.setInboundWebSocket(peer.isInbound()); + dto.setOutboundWebSocket(peer.isOutbound()); if (peer.isBlacklisted()) { dto.setBlacklistingCause(peer.getBlacklistingCause()); } diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/transaction/messages/update/CertificateLoader.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/transaction/messages/update/CertificateLoader.java deleted file mode 100644 index a4b46ba5a5..0000000000 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/transaction/messages/update/CertificateLoader.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.apollocurrency.aplwallet.apl.core.transaction.messages.update; - -import com.apollocurrency.aplwallet.apl.crypto.cert.ApolloCertificate; -import com.apollocurrency.aplwallet.apl.util.Version; -import lombok.extern.slf4j.Slf4j; - -import java.io.IOException; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.List; - - -/** - * Temporal class to load certs from filesystem for {@link com.apollocurrency.aplwallet.apl.core.transaction.types.update.UpdateV2TransactionType} transaction - * Should be removed, when p2p message exchange protocol will be implemented - * Moved from UpdaterV2 impl - */ -@Slf4j -public class CertificateLoader { - private final Class loadClass; - private final Version version; - - public CertificateLoader(Class tClass, Version appVersion) { - this.loadClass = tClass; - this.version = appVersion; - } - - public List loadAll() throws IOException { - Path rootPath = Paths.get(loadClass.getProtectionDomain().getCodeSource().getLocation().getPath()); - List certs = new ArrayList<>(); - Path fsPath = null; - if (rootPath.toUri().getScheme().equals("jar")) { - fsPath = rootPath; - } else if (Files.isRegularFile(rootPath)) { - String certsZipPath = "certs" + "-" + version + ".zip"; - fsPath = rootPath.getParent().resolve(certsZipPath); - } - if (fsPath != null) { - certs.addAll(readAllFromFs(fsPath)); - } else if (Files.isDirectory(rootPath)) { //classes - certs.addAll(readAll(rootPath)); - } else { - throw new RuntimeException("Unable to read certs from " + rootPath.toAbsolutePath()); - } - log.info("path {}, was read {} certs", rootPath.toAbsolutePath(), certs.size()); - return certs; - } - - private List readAll(Path path) throws IOException { - List certs = new ArrayList<>(); - Files.walkFileTree(path.resolve("certs"), new SimpleFileVisitor<>() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - try { - ApolloCertificate cert = ApolloCertificate.loadPEMFromPath(file.toAbsolutePath().toString()); - certs.add(cert); - } - catch (Exception e) { - log.error("Unable to load certificate from " + file, e); - } - return super.visitFile(file, attrs); - } - }); - return certs; - } - - private List readAllFromFs(Path path) throws IOException { - try (FileSystem fileSystem = FileSystems.newFileSystem(path, ClassLoader.getSystemClassLoader())) { - return readAll(fileSystem.getPath("/")); - } - } -} \ No newline at end of file diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/transaction/messages/update/CertificateLoaderProducer.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/transaction/messages/update/CertificateLoaderProducer.java deleted file mode 100644 index d63a8f8238..0000000000 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/transaction/messages/update/CertificateLoaderProducer.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright © 2018-2020 Apollo Foundation - */ - -package com.apollocurrency.aplwallet.apl.core.transaction.messages.update; - -import com.apollocurrency.aplwallet.apl.util.Constants; - -import jakarta.enterprise.inject.Produces; -import jakarta.inject.Singleton; - -@Singleton -public class CertificateLoaderProducer { - @Produces - @Singleton - public CertificateLoader loader() { - return new CertificateLoader(this.getClass(), Constants.VERSION); - } -} diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/transaction/messages/update/CertificateMemoryStore.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/transaction/messages/update/CertificateMemoryStore.java deleted file mode 100644 index 5735c31a6e..0000000000 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/transaction/messages/update/CertificateMemoryStore.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.apollocurrency.aplwallet.apl.core.transaction.messages.update; - -import com.apollocurrency.aplwallet.apl.crypto.cert.ApolloCertificate; -import com.apollocurrency.aplwallet.apl.util.cdi.config.Property; -import io.firstbridge.cryptolib.CryptoFactory; -import lombok.extern.slf4j.Slf4j; - -import jakarta.annotation.PostConstruct; -import jakarta.inject.Inject; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.math.BigInteger; -import java.net.MalformedURLException; -import java.net.URL; -import java.security.cert.X509Certificate; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -@Slf4j -@Singleton -public class CertificateMemoryStore { - - private CertificateLoader loader; - private Map certificates = new HashMap<>(); - private final URL caCertUrl; - - @Inject - public CertificateMemoryStore(@Property("updater.ca.cert-url") String caCertUrl, CertificateLoader loader) throws MalformedURLException { - this.loader = Objects.requireNonNull(loader); - String notNullCertUrl = Objects.requireNonNull(caCertUrl); - this.caCertUrl = new URL(notNullCertUrl); - } - - @PostConstruct - void init() { - List all = null; - try { - all = loader.loadAll(); - } catch (Exception e) { - log.debug("Error loading all certificates !", e); - } - X509Certificate rootCert = null; - try { - rootCert = CryptoFactory.newInstance().getKeyReader().readX509CertPEMorDER(caCertUrl.openStream()); - } catch (IOException e) { - log.debug("Error readX509 CertPEMorDER", e); - } - if (all != null) { - for (ApolloCertificate apolloCertificate : all) { - if (rootCert != null && !apolloCertificate.verify(rootCert)) { - throw new IllegalStateException("Certificate is not valid, ca signature verification failed for " + apolloCertificate); - } - if (apolloCertificate.isValid(new Date())) { - throw new IllegalStateException("Certificate is out of valid time range: " + apolloCertificate); - } - certificates.put(apolloCertificate.getSerial(), apolloCertificate); - } - } - } - - public ApolloCertificate getBySn(BigInteger sn) { - return certificates.get(sn); - } -} diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/security/id/IdentityService.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/security/id/IdentityService.java new file mode 100644 index 0000000000..9cf7a4291e --- /dev/null +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/security/id/IdentityService.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018-2021. Apollo Foundation. + */ +package com.apollocurrency.aplwallet.apl.security.id; + +import io.firstbridge.identity.handler.IdValidator; +import io.firstbridge.identity.handler.ThisActorIdHandler; + + +/** + * Service that handles identity of peers using X.509 certificates od nodes + * @author alukin@gmail.com + */ +public interface IdentityService { + + /** + * Handler for this node ID + * @return inited instance of ThisActorIdHandler + */ + ThisActorIdHandler getThisNodeIdHandler(); + + /** + * Inied with set of trusted CA certificates IdValidator instance + * @return Inied IdValidator instance + */ + IdValidator getPeerIdValidator(); + + /** + * Load this node certificates and keys from defined directories; + * Fails if certificate already exists but private key could not be loaded + * If certificate/private key pair does not exist, self-signed certificate is generated. + * @return true if key/certificate pair is loaded or generated and saved. + * false if certificate exists but corresponding private key could not be loaded + * or generated cert and key could not be saved. + */ + boolean loadMyIdentity(); + + /** + * Load set of trusted CA public certificates + */ + boolean loadTrustedCaCerts(); + +} diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/security/id/IdentityServiceImpl.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/security/id/IdentityServiceImpl.java new file mode 100644 index 0000000000..3123c5ad39 --- /dev/null +++ b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/security/id/IdentityServiceImpl.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2018-2021. Apollo Foundation. + */ +package com.apollocurrency.aplwallet.apl.security.id; + + + +import com.apollocurrency.aplwallet.apl.util.env.dirprovider.ConfigDirProvider; +import io.firstbridge.cryptolib.CryptoFactory; +import io.firstbridge.cryptolib.KeyWriter; +import io.firstbridge.identity.cert.ActorType; +import io.firstbridge.identity.cert.AuthorityID; +import io.firstbridge.identity.cert.CertAndKey; +import io.firstbridge.identity.cert.ExtCSR; +import io.firstbridge.identity.cert.ExtCert; +import io.firstbridge.identity.handler.CertificateLoader; +import io.firstbridge.identity.handler.CertificateLoaderImpl; +import io.firstbridge.identity.handler.IdValidator; +import io.firstbridge.identity.handler.IdValidatorImpl; +import io.firstbridge.identity.handler.PrivateKeyLoader; +import io.firstbridge.identity.handler.PrivateKeyLoaderImpl; +import io.firstbridge.identity.handler.ThisActorIdHandler; +import io.firstbridge.identity.handler.ThisActorIdHandlerImpl; +import lombok.extern.slf4j.Slf4j; + +import jakarta.inject.Inject; +import jakarta.inject.Singleton; +import java.io.IOException; +import java.nio.file.Path; +import java.security.PrivateKey; +import java.security.SecureRandom; +import java.util.List; + +/** + * Identity service implementation + * + * @author alukin@gmail.com + */ +@Slf4j +@Singleton +public class IdentityServiceImpl implements IdentityService { + + private ThisActorIdHandler thisNodeIdHandler; + private final IdValidator peerIdValidator; + public Path myCertPath; + public Path myKeyPath; + public Path apolloCaPath; + + private final ConfigDirProvider dirProvider; + + @Inject + public IdentityServiceImpl(ConfigDirProvider dirProvider) { + this.dirProvider=dirProvider; + this.peerIdValidator = new IdValidatorImpl(); + myCertPath = Path.of(dirProvider.getUserConfigLocation()) + .resolve("certificates") + .resolve(dirProvider.getChainIdPart()) + .resolve("this_node.crt"); + myKeyPath = Path.of(dirProvider.getUserConfigLocation()) + .resolve("keys") + .resolve(dirProvider.getChainIdPart()) + .resolve("this_node.key"); + apolloCaPath = Path.of(dirProvider.getInstallationConfigLocation()) + .resolve("conf") + .resolve("CA-certs"); + + } + + @Override + public ThisActorIdHandler getThisNodeIdHandler() { + return thisNodeIdHandler; + } + + @Override + public IdValidator getPeerIdValidator() { + return peerIdValidator; + } + + @Override + public boolean loadMyIdentity() { + boolean res = true; + CertificateLoader cl = new CertificateLoaderImpl(); + ExtCert myCert = cl.loadCert(myCertPath); + PrivateKey privKey = null; + if(myCert!=null){ + PrivateKeyLoader pkl = new PrivateKeyLoaderImpl(); + privKey = pkl.loadAndCheckPrivateKey(myKeyPath, myCert, null); + if(privKey==null){ + return false; + } + thisNodeIdHandler = new ThisActorIdHandlerImpl(myCert, privKey); + }else{ //we do not have node certificate yet, have to generate it + thisNodeIdHandler = new ThisActorIdHandlerImpl(); + CertAndKey certAndKey = thisNodeIdHandler.generateSelfSignedCert(fillCertProperties()); + + KeyWriter kw = CryptoFactory.newInstance().getKeyWriter(); + + try { + myKeyPath.getParent().toFile().mkdirs(); + kw.writePvtKeyPEM(myKeyPath.toString(), certAndKey.getPvtKey()); + myCertPath.getParent().toFile().mkdirs(); + kw.writeX509CertificatePEM(myCertPath.toString(), certAndKey.getCert()); + } catch (IOException ex) { + log.error("Can not wirite generated node keys"); + res=false; + } + + } + + return res; + } + + /** + * Fill the fields of X.509 certificate actually + * with some "placeholders" and generated NodeID + * @return filled CSR ready to sign or self-sign + */ + private ExtCSR fillCertProperties() { + //generate random 256-bit NodeID + byte[] nodeId = new byte[32]; + SecureRandom sr = new SecureRandom(); + sr.nextBytes(nodeId); + ExtCSR csr = new ExtCSR(); + + csr.setActorId(nodeId); + + AuthorityID authId = new AuthorityID(); + authId.setActorType(ActorType.NODE); + authId.setNetId(dirProvider.getChainId()); + authId.setAuthorityCode(0); + authId.setBusinessCode(0); + + csr.setAuthorityId(authId); + String email = csr.getActorIdAsHex()+"@apollowallet.org"; + csr.setCN(email); + csr.setOrg("Apollo blockchain"); + csr.setOrgUnit("Apollo-nodes"); + csr.setCity("Anywhere"); + csr.setCountry("US"); + csr.setEmail(email); + csr.setIP("127.0.0.1"); + csr.setDNSNames(csr.getActorIdAsHex()+".apollowallet.org"); + + return csr; + } + + @Override + public boolean loadTrustedCaCerts() { + CertificateLoader cl = new CertificateLoaderImpl(); + List caList = cl.loadCertsFromDir(apolloCaPath); + if(caList.isEmpty()){ + return false; + } + caList.forEach(cert -> { + peerIdValidator.addTrustedSignerCert(cert.getCertificate()); + }); + return true; + } + +} diff --git a/apl-core/src/main/resources/META-INF/beans.xml b/apl-core/src/main/resources/META-INF/beans.xml index e290abbacc..0178091e87 100644 --- a/apl-core/src/main/resources/META-INF/beans.xml +++ b/apl-core/src/main/resources/META-INF/beans.xml @@ -9,5 +9,6 @@ + \ No newline at end of file diff --git a/apl-core/src/test/java/com/apollocurrency/aplwallet/apl/testutil/EntityProducer.java b/apl-core/src/test/java/com/apollocurrency/aplwallet/apl/testutil/EntityProducer.java index a3c006c217..c0001115ff 100644 --- a/apl-core/src/test/java/com/apollocurrency/aplwallet/apl/testutil/EntityProducer.java +++ b/apl-core/src/test/java/com/apollocurrency/aplwallet/apl/testutil/EntityProducer.java @@ -32,6 +32,18 @@ public static Peer createPeer(final String host, final String announcedAddress, final PeerState state = active ? PeerState.CONNECTED : PeerState.NON_CONNECTED; Peer peer = new Peer() { + + @Override + public String getIdentity() { + return getHostWithPort(); + } + + @Override + public String getX509pem() { + return null; + } + + @Override public int compareTo(Peer o) { return 0; @@ -227,11 +239,6 @@ public String getHostWithPort() { return null; } - @Override - public boolean isTrusted() { - return false; - } - @Override public PeerTrustLevel getTrustLevel() { return PeerTrustLevel.NOT_TRUSTED; @@ -276,17 +283,11 @@ public void setServices(long code) { public void setLastUpdated(int time) { } - - @Override - public boolean isInboundSocket() { - return false; - } - + @Override - public boolean isOutboundSocket() { - return false; + public void setAnnouncedAddress(String addr){ + } - }; return peer; } diff --git a/apl-core/src/test/resources/test-env.properties b/apl-core/src/test/resources/test-env.properties index 30d0218f84..157a989aa1 100644 --- a/apl-core/src/test/resources/test-env.properties +++ b/apl-core/src/test/resources/test-env.properties @@ -2,5 +2,5 @@ # Copyright (c) 2018-2021. Apollo Foundation. # #comment out next property to increase the verbose level -#apl-test.env=quiet -apl-test.env=verbose +apl-test.env=quiet +#apl-test.env=verbose diff --git a/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/ActorType.java b/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/ActorType.java deleted file mode 100644 index 95fc533292..0000000000 --- a/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/ActorType.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.apollocurrency.aplwallet.apl.crypto.cert; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Arrays; - -/** - * @author alukin@gmail.com - */ -public class ActorType { - //actor types - public static final int NODE = 1; - public static final int SERVICE = 2; - public static final int PERSON = 3; - //actor sub-types for NODE - public static final int NODE_REGULAR = 0; - public static final int NODE_ARCHIVE = 1; - public static final int NODE_CERTIFIED_STORAGE = 2; - public static final int NODE_REGULAR_STORAGE = 3; - //actor sub-types for services - public static final int SERVICE_NONE = 0; - public static final int SERVICE_EXCHANE = 1; - public static final int SERVICE_WEBSITE = 2; - public static final int SERVICE_CDN = 3; - //actor sub-types for PERSON - public static final int PERSON_UNKNOWN = 0; - public static final int PERSON_DEVELOPER = 16; - public static final int PERSON_RELESE_ENG = 17; - public static final int PERSON_QUALITY_ASSURANCE = 18; - public static final int PERSON_DEV_MANAGEMENT = 19; - public static final int PERSON_DEVOPS = 20; - public static final int PERSON_MARKETING = 21; - - private int[] at = {0, 0}; - - public ActorType(int atype) { - ByteBuffer bb = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN).putInt(atype); - at[0] = bb.get(2); - at[1] = bb.get(3); - } - - public ActorType() { - } - - public Integer getValue() { - return at[0] << 8 | at[1]; - } - - public Integer getType() { - return at[0]; - } - - public void setType(int t) { - at[0] = t & 0xFF; - } - - public Integer getSubType() { - return at[1]; - } - - public void setSubType(int t) { - at[1] = t & 0xFF; - } - - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - - if (!ActorType.class.isAssignableFrom(obj.getClass())) { - return false; - } - - final ActorType other = (ActorType) obj; - if ((this.at == null) ? (other.at != null) : !Arrays.equals(this.at, other.at)) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - return at.hashCode(); - } - -} diff --git a/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/ApolloCSR.java b/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/ApolloCSR.java deleted file mode 100644 index 8acf11f039..0000000000 --- a/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/ApolloCSR.java +++ /dev/null @@ -1,322 +0,0 @@ -package com.apollocurrency.aplwallet.apl.crypto.cert; - -import io.firstbridge.cryptolib.CryptoNotValidException; -import io.firstbridge.cryptolib.KeyGenerator; -import io.firstbridge.cryptolib.KeyWriter; -import io.firstbridge.cryptolib.csr.CertificateRequestData; -import io.firstbridge.cryptolib.csr.X509CertOperations; -import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.openssl.PEMParser; -import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; -import org.bouncycastle.pkcs.PKCS10CertificationRequest; -import org.bouncycastle.util.IPAddress; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.FileReader; -import java.io.IOException; -import java.math.BigInteger; -import java.security.KeyPair; -import java.security.SecureRandom; -import java.security.cert.X509Certificate; - -/** - * Certificate signing request with Apollo-specific attributes - * - * @author alukin@gmail.com - */ -public class ApolloCSR extends CertBase { - - private static final Logger log = LoggerFactory.getLogger(ApolloCSR.class); - private final CertificateRequestData certData = new CertificateRequestData(CertificateRequestData.CSRType.HOST); - private String challengePassword = ""; - private BigInteger apolloID; - private AuthorityID apolloAuthID; - private final KeyWriter kw; - - public ApolloCSR() { - apolloID = new BigInteger(128, new SecureRandom()); - apolloAuthID = new AuthorityID(); - kw = factory.getKeyWriter(); - } - - public static ApolloCSR loadCSR(String path) { - PKCS10CertificationRequest cr; - ApolloCSR res = null; - try (FileReader fr = new FileReader(path)) { - PEMParser parser = new PEMParser(fr); - cr = (PKCS10CertificationRequest) parser.readObject(); - res = ApolloCSR.fromPKCS10(cr); - } catch (IOException ex) { - log.error("Can not read PKCS#10 file: " + path, ex); - } - return res; - } - - public static ApolloCSR fromPKCS10(PKCS10CertificationRequest cr) { - ApolloCSR res = new ApolloCSR(); - try { - CertAttributes va = new CertAttributes(); - va.setSubject(cr.getSubject()); - va.setAttributes(cr.getAttributes()); - res.setCN(va.getCn()); - res.setAuthID(va.getAuthorityId()); - res.setApolloID(va.getApolloId()); - res.setCountry(va.getCountry()); - res.setState(va.getState()); - res.setCity(va.getCity()); - res.setOrg(va.getO()); - res.setOrgUnit(va.getOu()); - - SubjectPublicKeyInfo pkInfo = cr.getSubjectPublicKeyInfo(); - JcaPEMKeyConverter converter = new JcaPEMKeyConverter(); - res.pubKey = converter.getPublicKey(pkInfo); - - } catch (ApolloCertificateException | IOException ex) { - log.error("Error reading public key frpm PKSC#10", ex); - } - return res; - } - - public static ApolloCSR fromCertificate(ApolloCertificate cert) { - ApolloCSR res = new ApolloCSR(); - res.setApolloAuthorityID(cert.getAuthorityId().getAuthorityID()); - BigInteger vid = cert.getApolloId(); - if (vid == null || vid == BigInteger.ZERO) { - vid = new BigInteger(128, new SecureRandom()); - } - res.setApolloID(vid); - res.setCN(cert.getCN()); - res.setEmail(cert.getEmail()); - res.setOrg(cert.getOrganization()); - res.setOrgUnit(cert.getOrganizationUnit()); - res.setCountry(cert.getCountry()); - res.setState(cert.getStateOrProvince()); - res.setCity(cert.getCity()); - res.setIP(cert.fromList(cert.getIPAddresses())); - res.setDNSNames(cert.fromList(cert.getDNSNames())); - res.pubKey = cert.getPublicKey(); - res.pvtKey = cert.getPrivateKey(); - return res; - } - - public static boolean isValidIPAddresList(String ipList) { - boolean res = true; - String[] addr = ipList.split(","); - for (String a : addr) { - res = IPAddress.isValid(a) || IPAddress.isValidWithNetMask(a); - if (!res) { - break; - } - } - return res; - } - - public static boolean isVaidDNSNameList(String nameList) { - boolean res = true; - String[] names = nameList.split(","); - String pattern = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$"; - for (String n : names) { - res = n.matches(pattern); - if (!res) { - break; - } - } - return res; - } - - public BigInteger getApolloID() { - return apolloID; - } - - public void setApolloID(BigInteger id) { - apolloID = id; - certData.setSubjectAttribute("UID", apolloID.toString(16)); - } - - public AuthorityID getApolloAuthorityID() { - return apolloAuthID; - } - - public void setApolloAuthorityID(BigInteger id) { - apolloAuthID = new AuthorityID(id); - certData.setSubjectAttribute("businessCategory", apolloAuthID.getAuthorityID().toString(16)); - } - - public AuthorityID getAuthID() { - return apolloAuthID; - } - - public void setAuthID(AuthorityID authID) { - this.apolloAuthID = authID; - certData.setSubjectAttribute("businessCategory", authID.getAuthorityID().toString(16)); - } - - public String getCN() { - String res = certData.getSubjectAttribute("CN"); - if (res == null) { - res = ""; - } - return res; - } - - public void setCN(String cn) { - certData.setSubjectAttribute("CN", cn); - } - - public String getEmial() { - String res = certData.getSubjectAttribute("emailAddress"); - if (res == null) { - res = ""; - } - return res; - } - - public void setEmail(String email) { - certData.setSubjectAttribute("emailAddress", email); - } - - public String getIP() { - return certData.getExtendedAttribute("subjaltnames.ipaddress"); - } - - public void setIP(String ip) { - if (ip != null && !ip.isEmpty()) { - if (isValidIPAddresList(ip)) { - certData.setExtendedAttribute("subjaltnames.ipaddress", ip); - } else { - throw new IllegalArgumentException("Invalid IP4 or IP6 addres: " + ip); - } - } - } - - public String getDNSNames() { - return certData.getExtendedAttribute("subjaltnames.dnsname"); - } - - public void setDNSNames(String n) { - if (n != null && !n.isEmpty()) { - if (isVaidDNSNameList(n)) { - certData.setExtendedAttribute("subjaltnames.dnsname", n); - } else { - throw new IllegalArgumentException("Invalid DNS name: " + n); - } - } - } - - public String getOrgUnit() { - return certData.getSubjectAttribute("OU"); - } - - public void setOrgUnit(String ou) { - certData.setSubjectAttribute("OU", ou); - } - - public String getOrg() { - return certData.getSubjectAttribute("O"); - } - - public void setOrg(String o) { - certData.setSubjectAttribute("O", o); - } - - public String getCountry() { - return certData.getSubjectAttribute("C"); - } - - public void setCountry(String c) { - certData.setSubjectAttribute("C", c); - } - - public String getState() { - return certData.getSubjectAttribute("ST"); - } - - public void setState(String c) { - certData.setSubjectAttribute("ST", c); - } - - public String getCity() { - return certData.getSubjectAttribute("L"); - } - - public void setCity(String c) { - certData.setSubjectAttribute("L", c); - } - - public String getChallengePassword() { - return challengePassword; - } - - public void setChallengePassword(String challengePassword) { - this.challengePassword = challengePassword; - } - - public String getPemPKCS10() { - String pem = ""; - try { - certData.processCertData(false); - if (pvtKey == null) { - newKeyPair(); - } - KeyPair kp = new KeyPair(pubKey, pvtKey); - X509CertOperations certOps = factory.getX509CertOperations(); - PKCS10CertificationRequest cr = certOps.createX509CertificateRequest(kp, certData, false, challengePassword); - pem = kw.getCertificateRequestPEM(cr); - } catch (IOException ex) { - log.error("Can not generate PKSC10 CSR", ex); - } catch (CryptoNotValidException ex) { - log.error("Can not generate PKSC10 CSR, Invalid data", ex); - } - return pem; - } - - public String getPrivateKeyPEM() { - String pem = ""; - try { - pem = kw.getPvtKeyPEM(pvtKey); - } catch (IOException ex) { - log.error("Can not get PEM of private key", ex); - } - return pem; - } - - public String getSelfSignedX509PEM() { - String pem = ""; - try { - certData.processCertData(true); - if (pvtKey == null) { - newKeyPair(); - } - KeyPair kp = new KeyPair(pubKey, pvtKey); - X509CertOperations certOps = factory.getX509CertOperations(); - X509Certificate cert = certOps.createSelfSignedX509v3(kp, certData); - pem = kw.getX509CertificatePEM(cert); - } catch (CryptoNotValidException | IOException ex) { - log.error("Can not generate self-signed PEM", ex); - } - return pem; - } - - @Override - public String toString() { - String res = "X.509 Certificate:\n"; - res += "CN=" + getCN() + "\n" - + "ApolloID=" + getApolloID().toString(16) + "\n"; - res += "emailAddress=" + getEmial() + "\n"; - res += "Country=" + getCountry() + " State/Province=" + getState() - + " City=" + getCity(); - res += "Organization=" + getOrg() + " Org. Unit=" + getOrgUnit() + "\n"; - res += "IP address=" + getIP() + "\n"; - res += "DNS names=" + getDNSNames() + "\n"; - return res; - } - - private void newKeyPair() { - KeyGenerator kg = factory.getKeyGenerator(); - KeyPair kp = kg.generateKeys(); - pubKey = kp.getPublic(); - pvtKey = kp.getPrivate(); - } - -} diff --git a/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/ApolloCertificate.java b/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/ApolloCertificate.java deleted file mode 100644 index 661b311251..0000000000 --- a/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/ApolloCertificate.java +++ /dev/null @@ -1,193 +0,0 @@ -package com.apollocurrency.aplwallet.apl.crypto.cert; - -import io.firstbridge.cryptolib.KeyReader; -import io.firstbridge.cryptolib.KeyWriter; -import io.firstbridge.cryptolib.impl.KeyReaderImpl; -import io.firstbridge.cryptolib.impl.KeyWriterImpl; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.SignatureException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -/** - * Represents X.509 certificate with Apollo-specific attributes and signed by - * Apollo CA or self-signed - * - * @author alukin@gmail.com - */ -public class ApolloCertificate extends CertBase { - - private static final Logger log = LoggerFactory.getLogger(ApolloCertificate.class); - - private final X509Certificate certificate; - private final CertAttributes cert_attr; - private final CertAttributes issuer_attr; - - public ApolloCertificate(X509Certificate certificate) throws ApolloCertificateException { - if (certificate == null) { - throw new ApolloCertificateException("Null certificate"); - } - this.certificate = certificate; - pubKey = certificate.getPublicKey(); - cert_attr = new CertAttributes(); - issuer_attr = new CertAttributes(); - cert_attr.setSubjectStr(certificate.getSubjectX500Principal().toString()); - issuer_attr.setSubjectStr(certificate.getIssuerX500Principal().toString()); - } - - public static ApolloCertificate loadPEMFromPath(String path) throws ApolloCertificateException, IOException { - ApolloCertificate res = null; - try (FileInputStream fis = new FileInputStream(path)) { - res = ApolloCertificate.loadPEMFromStream(fis); - } - return res; - } - - public static ApolloCertificate loadPEMFromStream(InputStream is) throws IOException, ApolloCertificateException { - KeyReader kr = new KeyReaderImpl(); - X509Certificate cert = kr.readX509CertPEMorDER(is); - ApolloCertificate ac = new ApolloCertificate(cert); - return ac; - } - - public BigInteger getApolloId() { - return cert_attr.getApolloId(); - } - - public AuthorityID getAuthorityId() { - return cert_attr.getAuthorityId(); - } - - - public String getCN() { - return cert_attr.getCn(); - } - - public String getOrganization() { - return cert_attr.getO(); - } - - public String getOrganizationUnit() { - return cert_attr.getOu(); - } - - public String getCountry() { - return cert_attr.getCountry(); - } - - public String getCity() { - return cert_attr.getCity(); - } - - public String getCertificatePurpose() { - return "Node"; - //TODO: implement recognitioin from extended attributes - } - - public List getIPAddresses() { - return cert_attr.IpAddresses(); - } - - public List getDNSNames() { - return null; - //TODO: implement - } - - public String getStateOrProvince() { - return null; - } - - public String getEmail() { - return cert_attr.geteMail(); - } - - public String fromList(List sl) { - String res = ""; - for (int i = 0; i < sl.size(); i++) { - String semicolon = i < sl.size() - 1 ? ";" : ""; - res += sl.get(i) + semicolon; - } - return res; - } - - public List fromString(String l) { - List res = new ArrayList<>(); - String[] ll = l.split(";"); - for (String s : ll) { - if (!s.isEmpty()) { - res.add(s); - } - } - return res; - } - - @Override - public String toString() { - String res = "Apollo X.509 Certificate:\n"; - res += "CN=" + cert_attr.getCn() + "\n" - + "ApolloID=" + getApolloId().toString(16) + "\n"; - - res += "emailAddress=" + getEmail() + "\n"; - res += "Country=" + getCountry() + " State/Province=" + getStateOrProvince() - + " City=" + getCity(); - res += "Organization=" + getOrganization() + " Org. Unit=" + getOrganizationUnit() + "\n"; - res += "IP address=" + fromList(getIPAddresses()) + "\n"; - res += "DNS names=" + fromList(getDNSNames()) + "\n"; - return res; - } - - public String getPEM() { - String res = ""; - KeyWriter kw = new KeyWriterImpl(); - try { - res = kw.getX509CertificatePEM(certificate); - } catch (IOException ex) { - log.error("Can not get certificate PEM", ex); - } - return res; - } - - public boolean isValid(Date date) { - boolean dateOK = false; - Date start = certificate.getNotBefore(); - Date end = certificate.getNotAfter(); - if (date != null && start != null && end != null) { - if (date.after(start) && date.before(end)) { - dateOK = true; - } else { - dateOK = false; - } - } - //TODO: implement more checks - return dateOK; - } - - public BigInteger getSerial() { - return certificate.getSerialNumber(); - } - - public CertAttributes getIssuerAttrinutes() { - return issuer_attr; - } - - public boolean verify(X509Certificate certificate) { - try { - this.certificate.verify(certificate.getPublicKey()); - } catch (CertificateException | NoSuchAlgorithmException | InvalidKeyException | NoSuchProviderException | SignatureException e) { - return false; - } - return true; - } -} diff --git a/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/ApolloCertificateException.java b/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/ApolloCertificateException.java deleted file mode 100644 index a1f666ba14..0000000000 --- a/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/ApolloCertificateException.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.apollocurrency.aplwallet.apl.crypto.cert; - -/** - * @author alukin@gmail.com - */ -public class ApolloCertificateException extends RuntimeException { - - ApolloCertificateException(String message) { - throw new RuntimeException(message); - } - -} diff --git a/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/AuthorityID.java b/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/AuthorityID.java deleted file mode 100644 index 05c52b6d37..0000000000 --- a/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/AuthorityID.java +++ /dev/null @@ -1,240 +0,0 @@ -package com.apollocurrency.aplwallet.apl.crypto.cert; - -import org.bouncycastle.util.encoders.Hex; - -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Arrays; - -/** - * Apollo AUthority ID is set of bits that classifies Apollo crypto actors and - * actor's capabilities. - * Bytes meaning. Les's number each of 16 bytes as following: - * 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 - * So bytes assigned to: - * 00 01 - actor type (00) and subtype (01), @see ActorType - * 02 03 - region code, not used yet - * 04 05 - business code, not used yet - * 06 07 - authority code, planned for usage together with business code for delegation tree - * 08 09 10 11 - operation code, planned for usage as operations permission mask - * 12 13 14 15 - supplemental code, reserved for future use - * - * @author alukin@gmail.com - */ -public class AuthorityID { - /** - * Length of AuthorityID in bytes - */ - public static final int LENGHT = 16; //16 bytes, 128 bit - - - private byte[] authorityID; - - public AuthorityID() { - setup(); - } - - public AuthorityID(BigInteger authID) { - setup(); - byte[] a = authID.toByteArray(); - int idx_dst = authorityID.length - 1; - int idx_src = a.length - 1; - while (idx_dst >= 0 && idx_src >= 0) { - authorityID[idx_dst] = a[idx_src]; - idx_src--; - idx_dst--; - } - } - - public AuthorityID(byte[] a) { - setup(); - int idx_dst = authorityID.length - 1; - int idx_src = a.length - 1; - while (idx_dst >= 0 && idx_src >= 0) { - authorityID[idx_dst] = a[idx_src]; - idx_src--; - idx_dst--; - } - } - - private void setup() { - authorityID = new byte[LENGHT]; - byte zero = 0; - Arrays.fill(authorityID, zero); - } - - public byte[] get() { - return authorityID; - } - - public BigInteger getAuthorityID() { - return new BigInteger(authorityID); - } - - /** - * ActorType and ActorSubType are first 2 most significant bytes of - * AuthorityID respectively - * - * @return 2 bytes of ActorType wrapped to 4 bytes of int - */ - public int getActorType() { - int res = authorityID[0] << 8 | authorityID[1]; - return res; - } - - /** - * Sets ActorType and ActorSubType as first 2 most significant bytes of - * AuthorityID respectively - * - * @param at 2 bytes wrapped in 2 least significant bytes of int - */ - public void setActorType(int at) { - ByteBuffer bb = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN).putInt(at); - authorityID[0] = bb.get(2); - authorityID[1] = bb.get(3); - } - - /** - * ActorType and ActorSubType are first 2 most significant bytes of - * AuthorityID respectively - * - * @return ActorType and ActorSubType wrapped in ActorType class - */ - public ActorType getApolloActorType() { - return new ActorType(getActorType()); - } - - /** - * Sets ActorType and ActorSubType as first 2 most significant bytes of - * uthorityID respectively - * - * @param vat ActorType class hat wraps those 2 bytes - */ - public void setApolloActorType(ActorType vat) { - setActorType(vat.getValue()); - } - - /** - * RegionCode is 2nd and 3rd most significant bytes of AuthorityID - * - * @return 2 bytes of RegionCode wrapped to 2 least significant bytes of int - */ - public Integer getRegionCode() { - int res = authorityID[2] << 8 | authorityID[3]; - return res; - } - - /** - * RegionCode is 2nd and 3rd most significant bytes of AuthorityID - * - * @param rc 2 bytes of RegionCode wrapped to 2 least significant bytes of - * int - */ - public void setRegionCode(int rc) { - ByteBuffer bb = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN).putInt(rc); - authorityID[2] = bb.get(2); - authorityID[3] = bb.get(3); - } - - /** - * BusinessCode is 4th and 5th most significant bytes of AuthorityID - * - * @return 2 bytes of BusinessCode wrapped to 2 least significant bytes of - * int - */ - public Integer getBusinessCode() { - int res = authorityID[4] << 8 | authorityID[5]; - return res; - } - - /** - * BusinessCode is 4th and 5th most significant bytes of AuthorityID - * - * @param bc 2 bytes of BusinessCode wrapped to 2 least significant bytes of - * int - */ - public void setBusinessCode(int bc) { - ByteBuffer bb = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN).putInt(bc); - authorityID[4] = bb.get(2); - authorityID[5] = bb.get(3); - } - - /** - * AuthorityCode is 6th and 7th most significant bytes of AuthorityID - * - * @return 2 bytes of AuthorityCode wrapped to 2 least significant bytes of - * int - */ - public Integer getAuthorityCode() { - int res = authorityID[6] << 8 | authorityID[7]; - return res; - } - - /** - * AuthorityCode is 6th and 7th most significant bytes of AuthorityID - * - * @param bc 2 bytes of AuthorityCode wrapped to 2 least significant bytes - * of int - */ - public void setAuthorityCode(int bc) { - ByteBuffer bb = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN).putInt(bc); - authorityID[6] = bb.get(2); - authorityID[7] = bb.get(3); - } - - public long getOperationCode() { - long res = authorityID[8] << 24 | authorityID[9] << 16 | authorityID[10] << 8 | authorityID[11]; - return res; - } - - public void setOperationCode(long oc) { - ByteBuffer bb = ByteBuffer.allocate(8).order(ByteOrder.BIG_ENDIAN).putLong(oc); - authorityID[8] = bb.get(4); - authorityID[9] = bb.get(5); - authorityID[10] = bb.get(6); - authorityID[11] = bb.get(7); - } - - public Long getSuplementalCode() { - long res = authorityID[12] << 24 | authorityID[13] << 16 | authorityID[14] << 8 | authorityID[15]; - return res; - } - - public void setSuplementalCode(long oc) { - ByteBuffer bb = ByteBuffer.allocate(8).order(ByteOrder.BIG_ENDIAN).putLong(oc); - authorityID[12] = bb.get(4); - authorityID[13] = bb.get(5); - authorityID[14] = bb.get(6); - authorityID[15] = bb.get(7); - } - - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - - if (!AuthorityID.class.isAssignableFrom(obj.getClass())) { - return false; - } - - final AuthorityID other = (AuthorityID) obj; - if ((this.authorityID == null) ? (other.authorityID != null) : !Arrays.equals(this.authorityID, other.authorityID)) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - return authorityID.hashCode(); - } - - @Override - public String toString() { - return "AuthorityID{" + "authorityID=" + Hex.toHexString(authorityID) + '}'; - } - -} diff --git a/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/CertAttributes.java b/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/CertAttributes.java deleted file mode 100644 index e5c963bb0a..0000000000 --- a/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/CertAttributes.java +++ /dev/null @@ -1,148 +0,0 @@ -package com.apollocurrency.aplwallet.apl.crypto.cert; - -import org.bouncycastle.asn1.pkcs.Attribute; -import org.bouncycastle.asn1.x500.X500Name; - -import java.math.BigInteger; -import java.util.List; - -/** - * PKCS#10 and X.509 attribute parser - * - * @author alukin@gmail.com - */ -public class CertAttributes { - - private BigInteger apolloId = BigInteger.ZERO; - private AuthorityID apolloAuthorityId = new AuthorityID(); - private String cn = ""; - private String o = ""; - private String ou = ""; - private String country = ""; - private String state = ""; - private String city = ""; - private String eMail = ""; - private List ipAddList = null; - - public CertAttributes() { - } - - public void setAttributes(Attribute[] aa) { - - } - - public void setSubject(X500Name sn) throws ApolloCertificateException { - String name = sn.toString(); - setSubjectStr(name); - } - - public void setSubjectStr(String name) throws ApolloCertificateException { - String[] names = name.split(","); - try { - for (String name1 : names) { - String[] nvs = name1.split("="); - String an = nvs[0].trim(); - String av = nvs.length > 1 ? nvs[1].trim() : ""; - if (an.equalsIgnoreCase("CN")) { - cn = av; - } else if (an.equalsIgnoreCase("O")) { - o = av; - } else if (an.equalsIgnoreCase("OU")) { - ou = av; - } else if (an.equalsIgnoreCase("C")) { - country = av; - } else if (an.equalsIgnoreCase("ST")) { - state = av; - } else if (an.equalsIgnoreCase("L")) { - city = av; - } else if (an.equalsIgnoreCase("EMAILADDRESS")) { - eMail = av; - } else if (an.trim().equalsIgnoreCase("UID")) { - apolloId = new BigInteger(av, 16); - } else if (an.equalsIgnoreCase("businessCategory") - || an.equalsIgnoreCase("OID.2.5.4.15")) { - apolloAuthorityId = new AuthorityID(new BigInteger(av, 16)); - } - } - } catch (NumberFormatException ex) { - throw new ApolloCertificateException(ex.getMessage()); - } - } - - public BigInteger getApolloId() { - return apolloId; - } - - public void setApolloId(BigInteger id) { - this.apolloId = id; - } - - public AuthorityID getAuthorityId() { - return apolloAuthorityId; - } - - public void setAuthorityId(AuthorityID authorityId) { - this.apolloAuthorityId = authorityId; - } - - public String getCn() { - return cn; - } - - public void setCn(String cn) { - this.cn = cn; - } - - public String getO() { - return o; - } - - public void setO(String o) { - this.o = o; - } - - public String getOu() { - return ou; - } - - public void setOu(String ou) { - this.ou = ou; - } - - public String getCountry() { - return country; - } - - public void setCountry(String country) { - this.country = country; - } - - public String getState() { - return state; - } - - public void setState(String state) { - this.state = state; - } - - public String getCity() { - return city; - } - - public void setCity(String city) { - this.city = city; - } - - public String geteMail() { - return eMail; - } - - public void seteMail(String eMail) { - this.eMail = eMail; - } - - List IpAddresses() { - return ipAddList; - } - -} diff --git a/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/CertBase.java b/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/CertBase.java deleted file mode 100644 index fdc1f76184..0000000000 --- a/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/CertBase.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.apollocurrency.aplwallet.apl.crypto.cert; - -import io.firstbridge.cryptolib.AsymCryptor; -import io.firstbridge.cryptolib.AsymKeysHolder; -import io.firstbridge.cryptolib.CryptoConfig; -import io.firstbridge.cryptolib.CryptoFactory; -import io.firstbridge.cryptolib.CryptoNotValidException; -import io.firstbridge.cryptolib.CryptoParams; - -import java.security.PrivateKey; -import java.security.PublicKey; - -/** - * Base class for certificate and CSR - * - * @author alukin@gmail.com - */ -public class CertBase { - - protected PublicKey pubKey = null; - protected PrivateKey pvtKey = null; - protected CryptoParams params = CryptoConfig.createDefaultParams(); - protected CryptoFactory factory = CryptoFactory.newInstance(params); - - public boolean checkKeys(PrivateKey pvtk) { - boolean res = false; - try { - String test = "Lazy Fox jumps ofver snoopy dog"; - AsymCryptor ac = factory.getAsymCryptor(); - AsymKeysHolder kn = new AsymKeysHolder(pubKey, pvtk, pubKey); - ac.setKeys(kn); - byte[] enc = ac.encrypt(test.getBytes()); - byte[] dec = ac.decrypt(enc); - String test_res = new String(dec); - res = test.compareTo(test_res) == 0; - } catch (CryptoNotValidException ex) { - } - return res; - } - - public PublicKey getPublicKey() { - return pubKey; - } - - public PrivateKey getPrivateKey() { - return pvtKey; - } - - public void setPrivateKey(PrivateKey pvtKey) { - this.pvtKey = pvtKey; - } -} diff --git a/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/CertificateHolder.java b/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/CertificateHolder.java deleted file mode 100644 index ecef4844d7..0000000000 --- a/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/CertificateHolder.java +++ /dev/null @@ -1,140 +0,0 @@ -package com.apollocurrency.aplwallet.apl.crypto.cert; - -import io.firstbridge.cryptolib.KeyReader; -import io.firstbridge.cryptolib.impl.KeyReaderImpl; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.math.BigInteger; -import java.security.PrivateKey; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -/** - * Holder of available cerificates placed in map with ID as a key - * - * @author alukin@gmail.com - */ -public class CertificateHolder { - public static final String PVT_SEARCH_PATH = "/../private/"; - private static final Logger log = LoggerFactory.getLogger(CertificateHolder.class); - private final Map> certMap = new TreeMap<>(); - - public static String rmSuffixes(String fn) { - String name = new String(fn); - String ext = ""; - int last_dot = fn.lastIndexOf("."); - if (last_dot >= 0) { - ext = fn.substring(last_dot + 1); - name = fn.substring(0, last_dot); - } - - String[] sfxes = {"_pvtkey", "_req", "_cert", "_selfcert", "_csr"}; - for (String s : sfxes) { - int idx = name.indexOf(s); - if (idx >= 0) { - name = name.substring(0, idx); - } - } - return name; - } - - public static String pvtKeyFileName(String fn) { - String suffix = "_pvtkey"; - String name = rmSuffixes(fn); - return name + suffix + ".pem"; - } - - public static String selfSignedFileName(String fn) { - String suffix = "_selfcert"; - String name = rmSuffixes(fn); - return name + suffix + ".pem"; - } - - public static String certFileName(String fn) { - String suffix = "_cert"; - String name = rmSuffixes(fn); - return name + suffix + ".pem"; - } - - public static String csrFileName(String fn) { - String suffix = "_csr"; - String name = rmSuffixes(fn); - return name + suffix + ".pem"; - } - - public List getCert(BigInteger id) { - return certMap.get(id); - } - - public void put(BigInteger id, ApolloCertificate cert) { - List cl = certMap.get(id); - if (cl == null) { - cl = new ArrayList<>(); - } - cl.add(cert); - certMap.put(id, cl); - } - - public int size() { - return certMap.size(); - } - - public void readCertDirectory(String path, boolean loadPrivateKey) { - File dir = new File(path); - if (dir.exists() && dir.isDirectory()) { - File[] filesList = dir.listFiles(); - for (File f : filesList) { - if (f.isFile() && f.canRead()) { - ApolloCertificate vc = null; - try { - vc = ApolloCertificate.loadPEMFromPath(f.getAbsolutePath()); - } catch (IOException ex) { - //impossible here - } catch (ApolloCertificateException ex) { - log.error("Certificate load exception wilr loading " + f.getAbsolutePath(), ex); - } - if (vc != null) { - put(vc.getApolloId(), vc); - if (loadPrivateKey) { - String parent = f.getParent(); - String fn = f.getName(); - PrivateKey pk = null; - pk = readPvtKey(parent + "/" + pvtKeyFileName(fn)); - if (pk == null) {//no key in the same dir, try ../private - pk = readPvtKey(parent + PVT_SEARCH_PATH + pvtKeyFileName(fn)); - } - if (pk != null) { - if (vc.checkKeys(pk)) { - vc.setPrivateKey(pk); - } else { - log.error("Private key file does not correspond to certificate: {}" + f.getAbsolutePath()); - } - } else { - log.error("Private key file not foud for certificate: {}", f.getAbsolutePath()); - } - } - } - } - } - } else { - log.error("Can not read certificates.Directory: {} does not exist!", path); - } - } - - public PrivateKey readPvtKey(String filePath) { - KeyReader kr = new KeyReaderImpl(); - PrivateKey res = null; - try (FileInputStream fis = new FileInputStream(filePath)) { - res = kr.readPrivateKeyPEM(fis); - } catch (IOException ex) { - log.trace("Can not read private key: {}", filePath); - } - return res; - } -} diff --git a/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/TrustAllSSLProvider.java b/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/TrustAllSSLProvider.java deleted file mode 100644 index e3ef5fbdec..0000000000 --- a/apl-crypto/src/main/java/com/apollocurrency/aplwallet/apl/crypto/cert/TrustAllSSLProvider.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright © 2013-2016 The Nxt Core Developers. - * Copyright © 2016-2018 Jelurida IP B.V. - * - * See the LICENSE.txt file at the top-level directory of this distribution - * for licensing information. - * - * Unless otherwise agreed in a custom licensing agreement with Jelurida B.V., - * no part of the Nxt software, including this file, may be copied, modified, - * propagated, or distributed except according to the terms contained in the - * LICENSE.txt file. - * - * Removal or modification of this copyright notice is prohibited. - * - */ - -package com.apollocurrency.aplwallet.apl.crypto.cert; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.X509Certificate; - -public class TrustAllSSLProvider { - - // Verify-all name verifier - private final static HostnameVerifier hostNameVerifier = (hostname, session) -> true; - - // Trust-all socket factory - private static final SSLSocketFactory sslSocketFactory; - - static { - TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { - public java.security.cert.X509Certificate[] getAcceptedIssuers() { - return null; - } - - public void checkClientTrusted(X509Certificate[] certs, String authType) { - } - - public void checkServerTrusted(X509Certificate[] certs, String authType) { - } - }}; - SSLContext sc; - try { - sc = SSLContext.getInstance("TLS"); - } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException(e); - } - try { - sc.init(null, trustAllCerts, new java.security.SecureRandom()); - } catch (KeyManagementException e) { - throw new IllegalStateException(e); - } - sslSocketFactory = sc.getSocketFactory(); - } - - public static HostnameVerifier getHostNameVerifier() { - return hostNameVerifier; - } - - public static SSLSocketFactory getSslSocketFactory() { - return sslSocketFactory; - } -} diff --git a/apl-dex/src/main/resources/META-INF/beans.xml b/apl-dex/src/main/resources/META-INF/beans.xml index 542bd53ab6..0178091e87 100644 --- a/apl-dex/src/main/resources/META-INF/beans.xml +++ b/apl-dex/src/main/resources/META-INF/beans.xml @@ -1,5 +1,14 @@ \ No newline at end of file + version="1.1" bean-discovery-mode="all"> + + org.jboss.weld.environment.se.threading.RunnableDecorator + + + + + + \ No newline at end of file diff --git a/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java b/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java index 9645f1cfec..4d4fa56e2e 100644 --- a/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java +++ b/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java @@ -18,6 +18,7 @@ import com.apollocurrency.aplwallet.apl.util.cdi.AplContainer; import com.apollocurrency.aplwallet.apl.util.cdi.AplContainerBuilder; import com.apollocurrency.aplwallet.apl.util.db.MariaDbProcess; +import com.apollocurrency.aplwallet.apl.core.db.JdbiTransactionalInterceptor; import com.apollocurrency.aplwallet.apl.util.env.EnvironmentVariables; import com.apollocurrency.aplwallet.apl.util.env.PosixExitCodes; import com.apollocurrency.aplwallet.apl.util.env.RuntimeEnvironment; @@ -289,13 +290,13 @@ public static void main(String[] argv) { //Configure CDI Container builder and start CDI container. From now all things must go CDI way AplContainerBuilder aplContainerBuilder = AplContainer.builder().containerId("MAIN-APL-CDI") + .beanClasses(JdbiTransactionalInterceptor.class) // do not use recursive scan because it violates the restriction to // deploy one bean for all deployment archives // Recursive scan will trigger base synthetic archive to load JdbiTransactionalInterceptor, which was already loaded by apl-core archive // See https://docs.jboss.org/cdi/spec/2.0.EDR2/cdi-spec.html#se_bootstrap for more details // we already have it in beans.xml in core .annotatedDiscoveryMode(); - //!!!!!!!!!!!!!! //TODO: turn it on periodically in development process to check CDI errors // Enable for development only, see http://weld.cdi-spec.org/news/2015/11/10/weld-probe-jmx/ diff --git a/apl-updater/src/main/resources/META-INF/beans.xml b/apl-updater/src/main/resources/META-INF/beans.xml index e290abbacc..0178091e87 100644 --- a/apl-updater/src/main/resources/META-INF/beans.xml +++ b/apl-updater/src/main/resources/META-INF/beans.xml @@ -9,5 +9,6 @@ + \ No newline at end of file diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/cdi/AplContainerBuilder.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/cdi/AplContainerBuilder.java index a11a231036..83a3018a6c 100644 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/cdi/AplContainerBuilder.java +++ b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/cdi/AplContainerBuilder.java @@ -8,7 +8,10 @@ import org.slf4j.LoggerFactory; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Objects; +import java.util.Set; import java.util.stream.Collectors; /** @@ -27,6 +30,8 @@ public class AplContainerBuilder { private List> interceptors; + private Set> beanClasses = new HashSet<>(); + private boolean concurrentDeploymentDisabled = false; // private List> recursiveScanPackages; @@ -66,6 +71,12 @@ public AplContainerBuilder interceptors(Class... interceptors) { return this; } + public AplContainerBuilder beanClasses(Class... beanClasses) { + Objects.requireNonNull(beanClasses); + this.beanClasses.addAll(Arrays.asList(beanClasses)); + return this; + } + // public AplContainerBuilder recursiveScanPackages(Class... recursiveScanPackages) { // if (recursiveScanPackages != null && recursiveScanPackages.length > 0) { // this.recursiveScanPackages = Arrays.stream(recursiveScanPackages).collect(Collectors.toList()); @@ -92,15 +103,17 @@ public AplContainer build() { if (interceptors != null && !interceptors.isEmpty()) { interceptors.forEach(weld::addInterceptor); } + weld.addBeanClasses(beanClasses.toArray(new Class[0])); if (devMode) { weld.enableDevMode(); + //it helps to localize problems! + weld.disableIsolation(); } if (concurrentDeploymentDisabled) { weld.property(ConfigurationKey.CONCURRENT_DEPLOYMENT.get(), "false"); } - WeldContainer newContainer = weld.initialize(); if (newContainer.isUnsatisfied()) { diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/cdi/transaction/JdbiHandleFactory.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/cdi/transaction/JdbiHandleFactory.java index 0cefad930a..24584b42a6 100644 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/cdi/transaction/JdbiHandleFactory.java +++ b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/cdi/transaction/JdbiHandleFactory.java @@ -5,6 +5,9 @@ import org.jdbi.v3.core.Handle; import org.jdbi.v3.core.Jdbi; import org.jdbi.v3.core.transaction.TransactionException; +import org.slf4j.Logger; + +import static org.slf4j.LoggerFactory.getLogger; /** * Holds opened connection {@link Handle} for current thread. diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/DefaultConfigDirProvider.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/DefaultConfigDirProvider.java index 704963529c..26788c82a7 100644 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/DefaultConfigDirProvider.java +++ b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/DefaultConfigDirProvider.java @@ -18,6 +18,28 @@ * Config dir provider which provide default config files locations */ public class DefaultConfigDirProvider implements ConfigDirProvider { + + /** + * Chain IDs ow known networks from 0 (mainnet) to 3rd testnet } + */ + protected static final String[] CHAIN_IDS = { + "b5d7b697-f359-4ce5-a619-fa34b6fb01a5", //main net + "a2e9b946-290b-48b6-9985-dc2e5a5860a1", //test net 1 + "2f2b6149-d29e-41ca-8c0d-f3343f5540c6", //test net 2 + "3fecf3bd-86a3-436b-a1d6-41eefc0bd1c6" //test net 3 + }; + + /** + * Deprecated names of configuration directories for known networks. Should + * be replaced later by chainID + */ + protected static final String[] CONF_DIRS = { + "conf", //main net + "conf-tn1", //test net 1 + "conf-tn2", //test net 2 + "conf-tn3" //test net 3 + }; + /** * Know network ID's including alias index and config-specific dir */ @@ -32,6 +54,9 @@ public class DefaultConfigDirProvider implements ConfigDirProvider { protected String applicationName; protected boolean isService; protected volatile ChainSpec chainSpec; + protected volatile String partialUuid; + protected volatile UUID chainUuid; + protected int netIndex; /** * Constructs config dir provider @@ -51,7 +76,7 @@ public DefaultConfigDirProvider(String applicationName, boolean isService, int n this.isService = isService; Optional byIndex = CHAINS.getByIndex(netIdx); - if (StringUtils.isBlank(uuidOrPart) && byIndex.isEmpty()){ + if (StringUtils.isBlank(uuidOrPart) && byIndex.isEmpty()) { this.chainSpec = CHAINS.getMainnet(); //default to main net if no params return; } @@ -60,8 +85,33 @@ public DefaultConfigDirProvider(String applicationName, boolean isService, int n "only one parameter: netIdx= " + netIdx + ", uuidOrPart " + uuidOrPart ); } - if (StringUtils.isNotBlank(uuidOrPart)) { + if (StringUtils.isNotBlank(uuidOrPart) && byIndex.isEmpty()) { this.chainSpec = CHAINS.findByChainId(uuidOrPart).orElse(ChainSpec.createExternal(uuidOrPart)); + int netIdxToAssign; + if (netIdx > CONF_DIRS.length - 1) { + System.err.println("Net index " + netIdx + " is greater than last known."); + netIdxToAssign = CONF_DIRS.length - 1; + System.err.println("Net index now is last one: " + netIdx); + } else { + netIdxToAssign = netIdx; + } + + if (netIdx >= 0) { + chainUuid = UUID.fromString(CHAIN_IDS[netIdx]); + } + + //find in known networks + if (uuidOrPart != null && !uuidOrPart.isEmpty()) { + for (int i = 0; i < CHAIN_IDS.length; i++) { + String id = CHAIN_IDS[i]; + if (id.startsWith(uuidOrPart.toLowerCase())) { + netIdxToAssign = i; + chainUuid = UUID.fromString(id); + break; + } + } + } + this.netIndex = netIdxToAssign; } else { this.chainSpec = byIndex.get(); } @@ -117,6 +167,9 @@ public void setChainID(UUID newID) { @Override public String getChainIdPart() { + if ( chainUuid != null && (partialUuid == null || partialUuid.isEmpty())) { + partialUuid = chainUuid.toString().substring(0,6); + } return chainSpec.getChainIdShortened(); } diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/ConnectionStatus.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/ConnectionStatus.java deleted file mode 100644 index 3b9ff7ca4a..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/ConnectionStatus.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.client; - -/** - * Sv connection status - * - * @author alukin@gmail.com - */ -public enum ConnectionStatus { - NOT_CONNECTD, - CONNECTING, - CONNECTED, - DISCONNECTED, - ERROR -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/MessageDispatcher.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/MessageDispatcher.java deleted file mode 100644 index 9bc967198f..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/MessageDispatcher.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.client; - -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusMessage; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusResponse; - -/** - * Public interface to message dispatcher. Though dispatcher is a core of - * messaging subsystem, this interface contains registration of processing - * routines only. - * - * @author alukin@gmail.com - */ -public interface MessageDispatcher { - - /** - * path to error handler. If not handler is not defined, default logging - * handler is used - */ - String ERROR_PATH = "/error"; - - /** - * Register handler for incoming messages - * - * @param pathSpec path specification as for JAX-RX REST services - * @param rqMapping mapping class for request - * @param respMapping mapping class for response - * @param handler handler routine - */ - void registerRqHandler(String pathSpec, Class rqMapping, Class respMapping, SvRequestHandler handler); - - /** - * Register response mapping class for specified path - * @param pathSpec path for which given response class should be mapped - * @param respClass class to which response for given path should be mapped - */ - void registerResponseMapping(String pathSpec, Class respClass); - - /** - * Register response mapping class for specifed path, which is parametrized by another class - * @param pathSpec path for which given response mapping is intended - * @param responseClass base parametrized mapping class - * @param paramClass parameter class for base class - */ - void registerParametrizedResponseMapping(String pathSpec, Class responseClass, Class paramClass); - - /** - * Unregister handler for incoming messages - * - * @param pathSpec exactly as in registration call - */ - void unregisterRqHandler(String pathSpec); -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/ResponseTimeoutException.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/ResponseTimeoutException.java deleted file mode 100644 index b762253caf..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/ResponseTimeoutException.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.apollocurrency.aplwallet.apl.util.supervisor.client; - -/** - * Represent exception occurred during sending request, when sender did not receive response for some amount of time - */ -public class ResponseTimeoutException extends RuntimeException{ - public ResponseTimeoutException(String message) { - super(message); - } - - public ResponseTimeoutException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/SubscribePath.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/SubscribePath.java deleted file mode 100644 index 1f6eed12b8..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/SubscribePath.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.client; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotation to authomtical registration of incomig message handler - * - * @author alukin@gmail.com - */ -@Retention(RetentionPolicy.SOURCE) -@Target(ElementType.METHOD) -public @interface SubscribePath { - - public String value() default "/*"; -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/SubscribePathAnnotationProcessor.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/SubscribePathAnnotationProcessor.java deleted file mode 100644 index 5432047b08..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/SubscribePathAnnotationProcessor.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.client; - -import java.util.LinkedHashSet; -import java.util.Set; -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.Filer; -import javax.annotation.processing.Messager; -import javax.annotation.processing.ProcessingEnvironment; -import javax.annotation.processing.RoundEnvironment; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.TypeElement; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; -import javax.tools.Diagnostic; - -/** - * Attention! Not complete, annotations do not work yet - * - * @author alukin@gmail.com - */ -public class SubscribePathAnnotationProcessor extends AbstractProcessor { - - private Messager messager; - private Types typesUtil; - private Elements elementsUtil; - private Filer filer; - - @Override - public synchronized void init(ProcessingEnvironment processingEnv) { - super.init(processingEnv); - messager = processingEnv.getMessager(); - typesUtil = processingEnv.getTypeUtils(); - elementsUtil = processingEnv.getElementUtils(); - filer = processingEnv.getFiler(); - } - - @Override - public boolean process(Set arg0, RoundEnvironment arg1) { - messager.printMessage(Diagnostic.Kind.WARNING, "========== processing subscribePath ============"); - return true; - } - - @Override - public Set getSupportedAnnotationTypes() { - Set annotations = new LinkedHashSet<>(); - annotations.add(SubscribePath.class.getCanonicalName()); - return annotations; - } - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latestSupported(); - } - -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/SvBusService.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/SvBusService.java deleted file mode 100644 index ec5ced6043..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/SvBusService.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.client; - -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusHello; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusRequest; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusResponse; - -import java.net.URI; -import java.util.Map; -import java.util.concurrent.CompletableFuture; - -/** - * Supervisor bus service, top part of communication API - * - * @author alukin@gmailcom - */ -public interface SvBusService { - - void addConnection(URI uri, boolean isDefault); - - void addResponseMapping(String path, Class tClass); - - void addParametrizedResponseMapping(String path, Class tClass, Class paramClass); - - Map getConnections(); - - MessageDispatcher getDispatcher(); - - T sendSync(SvBusRequest rq, String path, URI addr); - - CompletableFuture sendAsync(SvBusRequest msg, String path, URI addr); - - ConnectionStatus getConnectionStaus(URI uri); - - void shutdown(); - - void setMyInfo(SvBusHello info); - - URI getMyAddress(); -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/SvRequestHandler.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/SvRequestHandler.java deleted file mode 100644 index 190a8fb58b..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/SvRequestHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.client; - -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusRequest; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusResponse; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvChannelHeader; - -/** - * incoming message (request) handler prototype - * - * @author alukin@gmail.com - */ -public interface SvRequestHandler { - - /** - * handle command synchronously - * - * @param request - * @param header - * @return some reply message - */ - public SvBusResponse handleRequest(SvBusRequest request, SvChannelHeader header); -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/HandlerRecord.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/HandlerRecord.java deleted file mode 100644 index 7f795fc595..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/HandlerRecord.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.client.impl; - -import com.apollocurrency.aplwallet.apl.util.supervisor.client.SvRequestHandler; -import com.fasterxml.jackson.databind.JavaType; -import java.util.HashMap; -import java.util.Map; - -/** - * Record to save handler data and mappings - * - * @author alukin@gmail.com - */ -public class HandlerRecord { - - public String pathSpec; - public SvRequestHandler handler; - public JavaType respMapping; - public JavaType rqMapping; - public Map pathParams = new HashMap<>(); -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/MessageDispatcherImpl.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/MessageDispatcherImpl.java deleted file mode 100644 index c2dcf72a61..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/MessageDispatcherImpl.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.client.impl; - -import com.apollocurrency.aplwallet.apl.util.ThreadUtils; -import com.apollocurrency.aplwallet.apl.util.supervisor.client.MessageDispatcher; -import com.apollocurrency.aplwallet.apl.util.supervisor.client.ResponseTimeoutException; -import com.apollocurrency.aplwallet.apl.util.supervisor.client.SvRequestHandler; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusStatus; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusErrorCodes; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusHello; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusMessage; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusRequest; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusResponse; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvChannelHeader; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvChannelMessage; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.JsonNode; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; - -import java.net.SocketTimeoutException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Deque; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * Implementation of MessageDispoatcher. Actually it is the core of messaging - * system that performs message passing from remote side to processing routines - * and back - * - * @author alukin@gmail.com - */ -@Slf4j -public class MessageDispatcherImpl implements MessageDispatcher { - - public static long RESPONSE_WAIT_TIMEOUT_MS = 500L; // TODO need to make it configurable - public static final int SAY_HELLO_ATTEMPTS = 5; - private final SvSessions connections; - private final PathParamProcessor pathMatcher; - private final Deque outgoingQueue = new LinkedList<>(); - private SvBusHello hello; - @Getter - private URI myAddress = null; - //TODO - // Which thread pool to use here with response wait latches? - ExecutorService executor = Executors.newCachedThreadPool(); - private final Map waiting = new ConcurrentHashMap<>(); - - public MessageDispatcherImpl() { - pathMatcher = new PathParamProcessor(); - connections = new SvSessions(this); - registerRqHandler("/hello", SvBusRequest.class, SvBusResponse.class, (req, header)-> { - log.info("Hello received from {}" + header.from); - return new SvBusResponse(new SvBusStatus(0, "Hello OK")); - }); - registerResponseMapping("/hello", SvBusResponse.class); - } - - public Map getConnections() { - return connections.getAll(); - } - - /** - * - * @return request handler that matches path specification - */ - private HandlerRecord findRqByPath(String path) { - HandlerRecord handlerRec = pathMatcher.findAndParse(path); - return handlerRec; - } - - @Override - public void registerRqHandler(String pathSpec, Class rqMapping, Class respMapping, SvRequestHandler handler) { - pathMatcher.registerRqHandler(pathSpec, rqMapping, respMapping, handler); - } - - @Override - public void registerResponseMapping(String pathSpec, Class respClass) { - pathMatcher.registerResponseMapping(pathSpec, respClass, null); - } - - @Override - public void registerParametrizedResponseMapping(String pathSpec, Class responseClass, Class paramClass) { - pathMatcher.registerResponseMapping(pathSpec, responseClass, paramClass); - } - - @Override - public void unregisterRqHandler(String pathSpec) { - pathMatcher.remove(pathSpec); - } - - long nextMessageId() { - return Math.round(Math.random() * (Long.MAX_VALUE - 1)); - } - - boolean isMyAddress(String to) throws URISyntaxException { - return myAddress.equals(new URI(to)); - } - - public SvBusResponse errornousRequestsHandler(JsonNode rqBody, SvChannelHeader rqHeader, int code, String errorInfo) { - SvBusStatus error = new SvBusStatus(code, errorInfo + " Request path: " + rqHeader.path); - SvBusResponse resp = new SvBusResponse(error); - - return resp; - } - - void addConnection(URI uri, boolean isDefault) { - SvBusClient client = new SvBusClient(uri, this); - connections.put(uri, client, isDefault); - client.connect(); - } - - private T getResponse(Long rqId) throws SocketTimeoutException { - T res = null; - ResponseLatch l = waiting.get(rqId); - if (l != null) { - res = l.get(RESPONSE_WAIT_TIMEOUT_MS); - } - return res; - } - - /** - * Send message to the specified address and wait for response - * @param rq message payload - * @param path url path to which request will be sent. For url 'ws://127.0.0.1:8080/path/to/resource' path is 'path/to/resource' - * @param addr network address which recipient's websocket server listen to. Example: 'ws://127.0.0.1:8080' - * @param type of returned response - * @return received response for sent message - * @throws ResponseTimeoutException when recipient did not respond to sent message in {@link MessageDispatcherImpl#RESPONSE_WAIT_TIMEOUT_MS} ms - * @throws MessageSendingException when response or message payload could not be serialized/deserialized - */ - public T sendSync(SvBusMessage rq, String path, URI addr) { - SvBusClient client = connections.get(addr); - if (client == null) { - client = connections.getDefault().getValue(); - } - SvChannelHeader header = new SvChannelHeader(); - header.from = myAddress.toString(); - header.to = addr.toString(); - header.path = path; - header.messageId = nextMessageId(); - SvChannelMessage env = new SvChannelMessage(); - env.header = header; - env.body = rq; - try { - if (!client.sendMessage(env)) { - outgoingQueue.addLast(env); - } - waiting.put(header.messageId, new ResponseLatch()); - try { - return getResponse(header.messageId); - } catch (SocketTimeoutException e) { - throw new ResponseTimeoutException("Unable to get response after waiting for " + RESPONSE_WAIT_TIMEOUT_MS + " ms", e); - } - } catch (JsonProcessingException ex) { - throw new MessageSendingException("Can not map response to JSON", ex); - } - } - - public CompletableFuture sendAsync(SvBusRequest rq, String path, URI addr) { - CompletableFuture res = CompletableFuture.supplyAsync(() -> sendSync(rq, path, addr), executor); - return res; - } - - void sendHello(URI addr) { - sendSync(hello, "/hello", addr); - } - - void replyTo(SvChannelHeader rqHeader, SvBusMessage m) { - SvChannelHeader header = new SvChannelHeader(); - header.from = myAddress.toString(); - header.to = rqHeader.from; - //TODO: etire path or prefix only without path parameters? - header.path = rqHeader.path; - header.inResponseTo = rqHeader.messageId; - header.messageId = nextMessageId(); - SvBusClient client = connections.get(URI.create(header.to)); - if (client == null) { - client = connections.getDefault().getValue(); - } - SvChannelMessage env = new SvChannelMessage(); - env.body = m; - env.header = header; - try { - if (!client.sendMessage(env)) { - outgoingQueue.addLast(env); - } - } catch (JsonProcessingException ex) { - log.error("Can not map response to JSON"); - } - } - - void handleResponse(JsonNode body, SvChannelHeader header) { - ResponseLatch rl = waiting.get(header.inResponseTo); - if (rl == null) { - log.warn("Got responce that is not in waiting map. Header: {}", header); - } else { - JavaType responseType = pathMatcher.findResponseMappingClass(header.path); - if (responseType == null) { // Maybe set here error response to unlock latch? - if (header.path.equals(MessageDispatcher.ERROR_PATH)) { - log.error("Error reply without destination path: Header: {}, Body: {}", header, body); - } else { - log.error("No response mapper found for path: {}", header.path); - } - } else { - SvBusResponse response = pathMatcher.convertResponse(body, responseType); - rl.setResponse(response); - } - } - } - - void handleRequest(JsonNode body, SvChannelHeader header) { - HandlerRecord handlerRec = findRqByPath(header.path); - SvBusResponse response; - if (handlerRec != null) { - SvBusRequest rq = pathMatcher.convertRequest(body, handlerRec); - try { - response = handlerRec.handler.handleRequest(rq, header); - } catch (Exception e) { - log.error("Error in handler method for path {}", handlerRec.pathSpec, e); - response = errornousRequestsHandler(body, header, SvBusErrorCodes.PROCESSING_ERROR, e.getMessage()); - } - replyTo(header, response); - } else { - response = errornousRequestsHandler(body, header, SvBusErrorCodes.NO_HANDLER, "No handler registered."); - replyTo(header, response); - } - } - - void handleIncoming(SvChannelHeader header, JsonNode body) { - try { - if (!isMyAddress(header.to)) { - int res = routeMessage(header, body); - } else { - //TODO maybe better to encapsulate such logic inside header? - if (header.inResponseTo != null) { //this is response - handleResponse(body, header); - } else { - handleRequest(body, header); - } - } - } catch (URISyntaxException e) { - replyTo(header, new SvBusResponse(new SvBusStatus(1, "Incorrect target uri: " + header.to))); - } - } - - void onConnectionUp(URI uri) { - - SvBusClient client = connections.get(uri); - //should never happend - if (client == null) { - log.error("Connection {} was not added", uri); - return; - } - List toRemove = new ArrayList<>(); - trySayHello(uri); - boolean def = connections.isDefault(uri); - for (SvChannelMessage m : outgoingQueue) { - if (def || m.header.to.equals(uri.toString())) { - try { - if (client.sendMessage(m)) { - toRemove.add(m); - } - } catch (JsonProcessingException ex) { - log.error("Can not map message to JSON"); - } - } - } - - outgoingQueue.removeAll(toRemove); - } - - private void trySayHello(URI uri) { - int attempts = SAY_HELLO_ATTEMPTS; - while (true) { - attempts--; - try { - sendHello(uri); - break; - } catch (ResponseTimeoutException e) { - if (attempts == 0) { - throw new MessageSendingException("Unable to send hello to " + uri + " due to response timeout", e); - } - ThreadUtils.sleep(500); - } - } - } - - void shutdown() { - executor.shutdown(); - connections.close(); - } - - void setMyInfo(SvBusHello info) { - hello = info; - myAddress = URI.create(info.clientAddr); - } - - private int routeMessage(SvChannelHeader header, JsonNode body) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } - -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/MessageSendingException.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/MessageSendingException.java deleted file mode 100644 index 706ee0d3a2..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/MessageSendingException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.apollocurrency.aplwallet.apl.util.supervisor.client.impl; - -public class MessageSendingException extends RuntimeException { - public MessageSendingException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/PathParamProcessor.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/PathParamProcessor.java deleted file mode 100644 index 87509e9cc6..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/PathParamProcessor.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.client.impl; - -import com.apollocurrency.aplwallet.apl.util.supervisor.client.SvRequestHandler; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusMessage; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusRequest; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusResponse; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * JAX-RS -like path specifications processor - * - * @author alukin@gmail.com - */ -@Slf4j -public class PathParamProcessor { - - private final Map rqHandlers = new ConcurrentHashMap<>(); - private final Map responseMappingClasses = new ConcurrentHashMap<>(); - @Getter - private final ObjectMapper mapper; - - public PathParamProcessor() { - //init mapper - mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.enable(SerializationFeature.INDENT_OUTPUT); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - } - - boolean canDistinguish(String pathSpec) { - return true; - } - - public boolean registerRqHandler(String pathSpec, Class rqMapping, Class respMapping, SvRequestHandler handler) { - boolean res = false; - PathSpecification spec = PathSpecification.fromSpecString(pathSpec); - if (findHandler(spec.prefix) != null) { - log.error("Request handler for path specification with prefix {} is already registered", spec.prefix); - } else { - res = true; - HandlerRecord hrec = new HandlerRecord(); - hrec.pathSpec = pathSpec; - hrec.handler = handler; - hrec.rqMapping = mapper.constructType(rqMapping); - hrec.respMapping = mapper.constructType(respMapping); - rqHandlers.putIfAbsent(spec, hrec); - } - return res; - } - - public boolean registerResponseMapping(String pathSpec, Class respMapping, Class parametrizedClass) { - PathSpecification spec = PathSpecification.fromSpecString(pathSpec); - boolean alreadyExist = findResponseMappingClass(spec.prefix) != null; - if (alreadyExist) { - log.error("Response class for path specification with prefix {} is already registered", spec.prefix); - } else { - JavaType typeToRegister; - if (parametrizedClass != null) { - typeToRegister = mapper.getTypeFactory().constructParametricType(respMapping, parametrizedClass); - } else { - typeToRegister = mapper.constructType(respMapping); - } - responseMappingClasses.put(spec, typeToRegister); - } - return alreadyExist; - } - - public HandlerRecord findAndParse(String path) { - HandlerRecord res = null; - for (PathSpecification ps : rqHandlers.keySet()) { - if (ps.matches(path)) { - res = rqHandlers.get(ps); - res.pathParams.clear(); - res.pathParams.putAll(ps.parseParams(path)); - break; - } - } - return res; - } - - void remove(String pathSpec) { - for (PathSpecification ps : rqHandlers.keySet()) { - if (ps.pathSpec.equals(pathSpec)) { - rqHandlers.remove(ps); - break; - } - } - } - - public SvBusRequest convertRequest(JsonNode body, HandlerRecord hr) { - SvBusRequest res = mapper.convertValue(body, hr.rqMapping); - return res; - } - - public HandlerRecord findHandler(String path) { - return findOneBySpec(path, rqHandlers); - } - public JavaType findResponseMappingClass(String path) { - JavaType oneBySpec = findOneBySpec(path, responseMappingClasses); - return oneBySpec; - } - - private T findOneBySpec(String path, Map map) { - for (PathSpecification ps : map.keySet()) { - if (ps.matches(path)) { - return map.get(ps); - } - } - return null; - } - - public T convertResponse(JsonNode body, JavaType responseClass) { - T res = mapper.convertValue(body, responseClass); - return res; - } -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/PathSpecification.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/PathSpecification.java deleted file mode 100644 index f3249c29ba..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/PathSpecification.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.client.impl; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import lombok.extern.slf4j.Slf4j; - -/** - * Path specification as in JAX-RS example: /messages/{id}/{code} All values are - * handled as strings, it is up to processing code how to convert it - * - * @author alukin@gmail.com - */ -@Slf4j -public class PathSpecification { - - public String prefix; - public List paramNames = new ArrayList<>(); - public String pathSpec; - - public PathSpecification() { - } - - public static PathSpecification fromSpecString(String pathSpec) { - PathSpecification res = new PathSpecification(); - res.pathSpec = pathSpec; - String[] elements = pathSpec.split("/"); - int bracePos = pathSpec.indexOf("{"); - if (bracePos > 0) { - res.prefix = pathSpec.substring(0, bracePos - 1); - for (String element : elements) { - if (element.startsWith("{")) { - if (element.endsWith("}")) { - res.paramNames.add(element.substring(1, element.length() - 1)); - } else { //TODO consider throwing exception here - log.error("Missing brace in path element {} of path sepce: {}", element, pathSpec); - res.paramNames.add(element.substring(1, element.length())); - } - } - } - } else { - res.prefix = pathSpec; - } - - return res; - } - - public boolean matches(String path) { - boolean res = false; - int len = prefix.length(); - if (path.length() >= len) { - String matching = path.substring(0, len); - if (matching.equals(prefix)) { - res = true; - } - } - return res; - } - - public Map parseParams(String path) { - Map res = new HashMap<>(); - String params = path.substring(prefix.length()); - if (!params.isEmpty()) { - String[] elements = params.split("/"); - //first element after split() may be "" - int start = 0; - if (elements.length > 0) { - if (elements[0].isEmpty()) { - start = 1; - } - } - for (int i = start; i < elements.length; i++) { - if (i >= paramNames.size() + start) { - break; - } - res.put(paramNames.get(i - start), elements[i]); - } - } - return res; - } -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/ResponseLatch.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/ResponseLatch.java deleted file mode 100644 index c694aabad3..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/ResponseLatch.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.client.impl; - -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusResponse; -import lombok.extern.slf4j.Slf4j; - -import java.net.SocketTimeoutException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** - * Latch to response waiting - * - * @author alukin@gmail.com - */ -@Slf4j -public class ResponseLatch { - - /** - * time to live of entry. Entry should de deleted if it is older - */ - public static long WSW_TTL_MS = 60000; //1 minute - private final CountDownLatch latch = new CountDownLatch(1); - private final long createTime = System.currentTimeMillis(); - /** - * Response message - */ - private volatile SvBusResponse response; - - /** - * Wait for the response - *

- * The caller must hold the lock for the request condition - * - * @param timeoutMs Wait timeout - * @return Response message - * @throws java.net.SocketTimeoutException - */ - public T get(long timeoutMs) throws SocketTimeoutException { - try { - if (!latch.await(timeoutMs, TimeUnit.MILLISECONDS)) { - throw new SocketTimeoutException("WebSocket response wait timeout (" + timeoutMs + "ms) exceeded"); - } - } catch (InterruptedException ex) { - log.debug("Interruptrd exception while waiting for response", ex); - Thread.currentThread().interrupt(); - } - return (T) response; - } - - public void setResponse(T response) { - this.response = response; - latch.countDown(); - } - - public boolean isOld() { - long now = System.currentTimeMillis(); - boolean res = (now - createTime) > WSW_TTL_MS; - return res; - } -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/SvBusClient.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/SvBusClient.java deleted file mode 100644 index 2a0ac1ec03..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/SvBusClient.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.client.impl; - -import com.apollocurrency.aplwallet.apl.util.supervisor.client.ConnectionStatus; -import com.apollocurrency.aplwallet.apl.util.supervisor.client.MessageDispatcher; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusStatus; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusErrorCodes; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusResponse; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvChannelHeader; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvChannelMessage; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; - -import java.io.Closeable; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.WebSocket; -import java.net.http.WebSocket.Listener; -import java.nio.ByteBuffer; -import java.util.Date; -import java.util.concurrent.CompletionException; -import java.util.concurrent.CompletionStage; - -/** - * Client of Apollo Supervisor or similar service with the same protocol. - * - * @author alukin@gmail.com - */ -@Slf4j -public class SvBusClient implements Listener, Closeable { - - private ConnectionStatus state = ConnectionStatus.NOT_CONNECTD; - private WebSocket webSocket; - @Getter - private final URI serverURI; - private final HttpClient httpClient; - - private PathParamProcessor pathProcessor; - private final MessageDispatcherImpl dispatcher; - - public SvBusClient(URI serverURI, MessageDispatcher dispatcher) { - this.pathProcessor = new PathParamProcessor(); - this.dispatcher = (MessageDispatcherImpl) dispatcher; - this.serverURI = serverURI; - httpClient = HttpClient.newHttpClient(); - - } - - public boolean isConnected() { - return state == ConnectionStatus.CONNECTED; - } - - public ConnectionStatus getState() { - return state; - } - - private void setState(ConnectionStatus cs) { - state = cs; - } - - /** - * Connect to given by constructor URI - * - * @return true if connected - */ - public boolean connect() { - boolean res; - setState(ConnectionStatus.CONNECTING); - try { - webSocket = httpClient.newWebSocketBuilder() - .buildAsync(serverURI, this) - .join(); - res = !webSocket.isInputClosed(); - if (res) { - dispatcher.onConnectionUp(serverURI); - } - } catch (CompletionException ex) { - setState(ConnectionStatus.ERROR); - log.info("Can not connect to {}", serverURI); - res = false; - } catch (Exception e) { - res = false; - setState(ConnectionStatus.ERROR); - log.error("Unknown error occurred during connection to " + serverURI, e); - } - return res; - } - - public WebSocket getWebSocket() { - return webSocket; - } - - public boolean sendMessage(SvChannelMessage envelope) throws JsonProcessingException { - boolean res = false; - //TODO: binary mode with binary header - envelope.header.from_timestamp = new Date(); - ObjectMapper mapper = pathProcessor.getMapper(); - String msg = mapper.writeValueAsString(envelope); - if (webSocket != null) { - webSocket.sendText(msg, true); - //TODO may be join() ? - res = true; - } else { - log.error("Websocket is not connected error"); - } - return res; - } - - public void sendError(int code, String message, SvChannelHeader rqheader) { - SvBusStatus error = new SvBusStatus(code, message); - SvBusResponse resp = new SvBusResponse(error); - SvChannelHeader hdr = new SvChannelHeader(); - hdr.from = dispatcher.getMyAddress().toString(); - if (rqheader != null) { - hdr.to = rqheader.from; - hdr.path = rqheader.path; - hdr.inResponseTo = hdr.messageId; - } else { - hdr.to = serverURI.toString(); - hdr.path = MessageDispatcher.ERROR_PATH; - hdr.inResponseTo = 0L; - } - hdr.from_timestamp = new Date(); - hdr.messageId = dispatcher.nextMessageId(); - SvChannelMessage msg = new SvChannelMessage(hdr, resp); - try { //trying my besr, no result check - sendMessage(msg); - } catch (JsonProcessingException ex) { - } - } - -// should be common for binary and text mode - private void processIncoming(CharSequence data, boolean bin) { - try { - ObjectMapper mapper = pathProcessor.getMapper(); - JsonNode env_node = mapper.readTree(data.toString()); - JsonNode header_node = env_node.findValue("header"); - if (header_node == null) { - sendError(SvBusErrorCodes.INVALID_HEADER, "no header node in JSON", null); - log.error("No header in incoming message"); - return; - } - SvChannelHeader header = mapper.treeToValue(header_node, SvChannelHeader.class); - if (header == null) { - log.error("Can not parse header. Message: {}", data); - sendError(SvBusErrorCodes.INVALID_HEADER, "Invalid header node in JSON", null); - return; - } - JsonNode body = env_node.findValue("body"); // same as above, i think that better to add validation for npes to guarantee message correct format - if (body == null) { - log.warn("No body node in JSON"); - } - dispatcher.handleIncoming(header, body); - } catch (JsonProcessingException ex) { - sendError(SvBusErrorCodes.INVALID_MESSAGE, "Invalud JSON message: " + ex.getMessage(), null); - log.error("JSON processing error. Message: {}", data, ex); - } - } - - //TODO: implement - private SvChannelMessage decodeBinary(ByteBuffer data) { - log.error("Binary mode is not implemented yet"); - return null; - } - - //TODO: implement - private ByteBuffer encodeBinary(SvChannelMessage data) { - log.error("Binary mode is not implemented yet"); - return null; - } - - @Override - public CompletionStage onText(WebSocket webSocket, CharSequence data, boolean last) { - - log.debug("onText: {}", data); - processIncoming(data, false); - return Listener.super.onText(webSocket, data, last); - } - - @Override - public void onOpen(WebSocket webSocket) { - setState(ConnectionStatus.CONNECTED); - Listener.super.onOpen(webSocket); - } - - @Override - public CompletionStage onClose(WebSocket webSocket, int statusCode, - String reason) { - log.debug("onClose: {} {}", statusCode, reason); - setState(ConnectionStatus.DISCONNECTED); - return Listener.super.onClose(webSocket, statusCode, reason); - } - - @Override - public void onError(WebSocket webSocket, Throwable error) { - setState(state.ERROR); //TODO maybe save or print error stacktrace - log.debug("Error: ", error); - Listener.super.onError(webSocket, error); - } - - @Override - public CompletionStage onPong(WebSocket webSocket, ByteBuffer message) { - log.debug("onPong: "); - return Listener.super.onPong(webSocket, message); - } - - @Override - public CompletionStage onPing(WebSocket webSocket, ByteBuffer message) { - log.debug("onPing: "); - return Listener.super.onPing(webSocket, message); - } - - @Override - public CompletionStage onBinary(WebSocket webSocket, ByteBuffer data, boolean last) { - - // processIncoming(webSocket, decodeBinary(data), true); - return Listener.super.onBinary(webSocket, data, last); - } - - @Override - public void close() { - if (webSocket != null) { - webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok"); - } - } - - void sendText(CharSequence value) { - webSocket.sendText(value, true); - } -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/SvBusServiceImpl.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/SvBusServiceImpl.java deleted file mode 100644 index eb12631332..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/SvBusServiceImpl.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.client.impl; - -import com.apollocurrency.aplwallet.apl.util.supervisor.client.ConnectionStatus; -import com.apollocurrency.aplwallet.apl.util.supervisor.client.MessageDispatcher; -import com.apollocurrency.aplwallet.apl.util.supervisor.client.SvBusService; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusHello; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusRequest; -import com.apollocurrency.aplwallet.apl.util.supervisor.msg.SvBusResponse; - -import java.net.URI; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.CompletableFuture; - -/** - * Implementation of bus service - * - * @author alukin@gmail.com - */ -public class SvBusServiceImpl implements SvBusService { - - private final MessageDispatcherImpl dispatcher; - - public SvBusServiceImpl() { - SvBusHello hello = new SvBusHello(); - hello.clientPID = ProcessHandle.current().pid(); - hello.clientExePath = ""; - hello.clientInfo = "SvClient"; - dispatcher = new MessageDispatcherImpl(); - } - - @Override - public void addConnection(URI uri, boolean isDefault) { - dispatcher.addConnection(uri, isDefault); - } - - @Override - public void addResponseMapping(String path, Class tClass) { - dispatcher.registerResponseMapping(path, tClass); - } - - @Override - public void addParametrizedResponseMapping(String path, Class tClass, Class paramClass) { - dispatcher.registerParametrizedResponseMapping(path, tClass, paramClass); - } - - @Override - public Map getConnections() { - Map clients = dispatcher.getConnections(); - Map statuses = new HashMap<>(); - for (URI key : clients.keySet()) { - statuses.put(key, clients.get(key).getState()); - } - return statuses; - } - - @Override - public MessageDispatcher getDispatcher() { - return dispatcher; - } - - @Override - public T sendSync(SvBusRequest rq, String path, URI addr) { - T resp = dispatcher.sendSync(rq, path, addr); - return resp; - } - - @Override - public CompletableFuture sendAsync(SvBusRequest msg, String path, URI addr) { - return dispatcher.sendAsync(msg, path, addr); - } - - @Override - public ConnectionStatus getConnectionStaus(URI uri) { - Map statuses = getConnections(); - ConnectionStatus res = statuses.get(uri); - return res; - } - - @Override - public void shutdown() { - dispatcher.shutdown(); - } - - @Override - public URI getMyAddress() { - return dispatcher.getMyAddress(); - } - - @Override - public void setMyInfo(SvBusHello info) { - dispatcher.setMyInfo(info); - } - -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/SvSessions.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/SvSessions.java deleted file mode 100644 index 70cb8bc31e..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/SvSessions.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.client.impl; - -import com.apollocurrency.aplwallet.apl.util.supervisor.client.ConnectionStatus; -import lombok.extern.slf4j.Slf4j; - -import java.net.URI; -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Set of all connections inited - * - * @author alukin@gmail.com - */ -@Slf4j -public class SvSessions { - - private final Map connections = new ConcurrentHashMap<>(); - private final Timer timer; - public static final long CONNECT_INTERVAL_MS = 5000; - private Map.Entry defaultConnection; - private final MessageDispatcherImpl dispatecher; - - public SvSessions(MessageDispatcherImpl dispatecher) { - this.dispatecher = dispatecher; - //init connection restore timer task - //TODO: use our thread pool manager maybe - //TODO: ScheduledThreadPoolExecutor is preferred to Timer, better to use it - timer = new Timer("SypervisorConnectionChekcer", true); - timer.scheduleAtFixedRate(new TimerTask() { - @Override - public void run() { - for (URI key : connections.keySet()) { - SvBusClient client = connections.get(key); - if (!client.isConnected() && client.getState() != ConnectionStatus.CONNECTING) { - boolean res = client.connect(); - log.debug("Connection attempt to URI {} result: {}, state: {}", key, res, - client.getState() - ); - if (res) { - dispatecher.onConnectionUp(key); - } - } - } - } - - }, 0, CONNECT_INTERVAL_MS); - } - - public Map getAll() { - return connections; - } - - void put(URI uri, SvBusClient client, boolean isDefault) { - boolean setDefault = false; - //first one is default even if isDefault is false - if (connections.isEmpty()) { - setDefault = true; - } - connections.putIfAbsent(uri, client); - if (setDefault || isDefault) { - defaultConnection = connections.entrySet().iterator().next(); - } - } - - boolean isDefault(URI addr) { - return defaultConnection != null && defaultConnection.getKey().equals(addr); - } - - SvBusClient get(URI addr) { - return connections.get(addr); - } - - Map.Entry getDefault() { - return defaultConnection; - } - - void close() { - timer.cancel(); - connections.values().forEach(c -> { - c.close(); - }); - } - -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvBusErrorCodes.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvBusErrorCodes.java deleted file mode 100644 index e7d8a80775..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvBusErrorCodes.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.msg; - -/** - * Error codes for communication channel - * - * @author alukin@gmail.com - */ -public class SvBusErrorCodes { - - public static final int OK = 0; - public static final int NOT_CONNECTED = 1; - public static final int NO_ROUTE = 2; - public static final int NO_HANDLER = 3; - public static final int PROCESSING_ERROR = 4; - public static final int INVALID_HEADER = 5; - public static final int INVALID_MESSAGE = 6; - public static final int INVALID_BODY = 7; - public static final int RESPONSE_TIMEOUT = 8; -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvBusHello.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvBusHello.java deleted file mode 100644 index e76a7573c9..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvBusHello.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.msg; - -import com.fasterxml.jackson.annotation.JsonInclude; - -/** - * Hello message to be sent by any client on connection. It is needed to say - * server client's address in header and other info - * - * @author alukin@gmail.con - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -public class SvBusHello extends SvBusRequest { - - public Long clientPID; - public String clientExePath; - public String clientAddr; - public String clientInfo; -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvBusMessage.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvBusMessage.java deleted file mode 100644 index 59f2055d90..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvBusMessage.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.msg; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import lombok.Getter; -import lombok.Setter; - -/** - * Simple message on bus - * - * @author alukin@gmail.com - */ -@JsonInclude(Include.NON_NULL) -@Getter -@Setter -public class SvBusMessage { - - private String message; -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvBusRequest.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvBusRequest.java deleted file mode 100644 index 24c913161f..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvBusRequest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.msg; - -import com.fasterxml.jackson.annotation.JsonInclude; -import java.util.HashMap; -import java.util.Map; - -/** - * Request (incoming message) in SV channel - * - * @author alukin@gmail.com - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -public class SvBusRequest extends SvBusMessage { - - private final Map parameters = new HashMap<>(); - - public SvBusRequest(Map parameters) { - this.parameters.putAll(parameters); - } - - public SvBusRequest() {} - - public void add(T t, V v) { - parameters.put(t.toString(), v.toString()); - } - - public String get(String param) { - return parameters.get(param); - } - -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvBusResponse.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvBusResponse.java deleted file mode 100644 index 9c150bd47b..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvBusResponse.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.msg; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; - -/** - * This class represents REST response in the channel - * - * @author alukin@gmail.com - */ -@EqualsAndHashCode(callSuper = true) -@JsonInclude(Include.NON_NULL) -@Data -@AllArgsConstructor -@NoArgsConstructor -public class SvBusResponse extends SvBusMessage { - - /** - * Error code, 0 or null means success - */ - private SvBusStatus status; - - - @JsonIgnore - public boolean isSuccessful() { - return status == null || status.getCode() == 0; - } -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvBusStatus.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvBusStatus.java deleted file mode 100644 index 91ac71f25d..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvBusStatus.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.msg; - -import com.fasterxml.jackson.annotation.JsonInclude; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * Status message body on the bus - * - * @author alukin@gmail.com - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -@Data -@AllArgsConstructor -@NoArgsConstructor -public class SvBusStatus { - - private Integer code = 0; - private String description = "OK"; -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvChannelHeader.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvChannelHeader.java deleted file mode 100644 index 6f7300afee..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvChannelHeader.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.msg; - -import com.fasterxml.jackson.annotation.JsonInclude; -import java.util.Date; - -/** - * This class represents "envelope" header format for all messages going trough - * messaging systems of Apollo Supervisor Null fields ignored on serializing. - * - * @author alukinb@gmail.conm - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -public class SvChannelHeader { - - /** - * Each message has random unique ID - */ - public Long messageId; - /** - * If message is not request but response it should have this set to message - * Id of request. If it is null, message is request or just message that - * does not require response. - */ - public Long inResponseTo; - /** - * Often we have to route request to some REST API or use publish/subscribe - * magic for messages. Type of request or message going to this path is - * fixed and we interpret it inside of appropriate processing routine. with - * path parameters and request parameters - */ - public String path; - - public String from; - public String to; - public String routedBy; - public Date from_timestamp; - public Date route_timestamp; - -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvChannelMessage.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvChannelMessage.java deleted file mode 100644 index fd9a560751..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvChannelMessage.java +++ /dev/null @@ -1,22 +0,0 @@ - -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.msg; - -import lombok.AllArgsConstructor; -import lombok.NoArgsConstructor; - -/** - * This class represents "envelope" message format for all - * messages going trough messaging systems of Apollo Supervisor - * Null fields ignored on serializing. - * @author alukinb@gmail.conm - */ -@NoArgsConstructor -@AllArgsConstructor -public class SvChannelMessage { - public SvChannelHeader header = new SvChannelHeader(); - public Object body; -} - diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvCommandRequest.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvCommandRequest.java deleted file mode 100644 index e9f822027f..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvCommandRequest.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.msg; - -import com.fasterxml.jackson.annotation.JsonInclude; -import java.util.HashMap; - -/** - * This class represents command request to supervisor - * - * @author alukin@gmail.com - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -public class SvCommandRequest extends SvBusRequest { - - public String cmd; - public HashMap params = new HashMap<>(); -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvCommandResponse.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvCommandResponse.java deleted file mode 100644 index e72f4ff719..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/SvCommandResponse.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.msg; - -import com.fasterxml.jackson.annotation.JsonInclude; -import java.util.ArrayList; -import java.util.List; - -/** - * Responce to incoming command message - * - * @author alukin@gmail.com - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -public class SvCommandResponse extends SvBusResponse { - - public List out = new ArrayList<>(); - public List err = new ArrayList<>(); - - public SvCommandResponse(SvBusStatus error) { - super(error); - } -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/UpdateMessage.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/UpdateMessage.java deleted file mode 100644 index 676e824df5..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/supervisor/msg/UpdateMessage.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright © 2020 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.msg; - -import com.fasterxml.jackson.annotation.JsonInclude; - -/** - * Update indication message TODO: adapt it for uptater2 - * - * @author alukin@gmail.com - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -public class UpdateMessage extends SvBusMessage { - - public String version; - public Integer priority; -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/ws/WSClient.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/ws/WSClient.java deleted file mode 100644 index 652874921a..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/ws/WSClient.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright © 2018 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.ws; - -import java.io.Closeable; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.WebSocket; -import java.net.http.WebSocket.Listener; - -/** - * JDK-11 and above WebSocket client without any external dependencies - * - * @author alukin@gmail.com - */ -public class WSClient implements Closeable { - - private Listener wsListener; - private HttpClient client; - private WebSocket webSocket; - - public WebSocket getWebSocket() { - return webSocket; - } - - public WSClient(Listener wsListener) { - this.wsListener = wsListener; - client = HttpClient.newHttpClient(); - } - - /** - * Connect to given URI - * - * @param uri Example: "wss://localhost:8443/wsEndpoint" - * @return true if connected - */ - public boolean connect(String uri) { - boolean res = false; - webSocket = client.newWebSocketBuilder() - .buildAsync(URI.create(uri), wsListener) - .join(); - return !webSocket.isInputClosed(); - } - - public void sendText(String text) { - webSocket.sendText(text, true); - } - - @Override - public void close() { - webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok"); - } -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/ws/WSListener.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/ws/WSListener.java deleted file mode 100644 index 361d59bbe7..0000000000 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/ws/WSListener.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright © 2018 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.util.ws; - -import java.net.http.WebSocket; -import java.net.http.WebSocket.Listener; -import java.util.concurrent.CompletionStage; - -/** - * Simple web socket listener to work with Apl Supervisor protocol - * - * @author alukin@gmail.com - */ -public class WSListener implements Listener { - - @Override - public CompletionStage onText(WebSocket webSocket, - CharSequence data, boolean last) { - - System.out.println("onText: " + data); - - return Listener.super.onText(webSocket, data, last); - } - - @Override - public void onOpen(WebSocket webSocket) { - System.out.println("onOpen"); - Listener.super.onOpen(webSocket); - } - - @Override - public CompletionStage onClose(WebSocket webSocket, int statusCode, - String reason) { - System.out.println("onClose: " + statusCode + " " + reason); - return Listener.super.onClose(webSocket, statusCode, reason); - } -} diff --git a/apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/cert/ApolloCertificateTest.java b/apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/cert/ApolloCertificateTest.java deleted file mode 100644 index 4ed1491d58..0000000000 --- a/apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/cert/ApolloCertificateTest.java +++ /dev/null @@ -1,189 +0,0 @@ -package com.apollocurrency.aplwallet.apl.util.cert; - -import com.apollocurrency.aplwallet.apl.crypto.cert.ApolloCertificate; -import com.apollocurrency.aplwallet.apl.crypto.cert.ApolloCertificateException; -import com.apollocurrency.aplwallet.apl.crypto.cert.AuthorityID; -import com.apollocurrency.aplwallet.apl.crypto.cert.CertAttributes; -import io.firstbridge.cryptolib.CryptoConfig; -import io.firstbridge.cryptolib.CryptoParams; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; -import java.util.Date; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** - * @author alukin@gmail.com - */ -public class ApolloCertificateTest { - - private static final CryptoParams params = CryptoConfig.createDefaultParams(); - private static final org.slf4j.Logger log = LoggerFactory.getLogger(ApolloCertificateTest.class); - static ApolloCertificate acert; - - public ApolloCertificateTest() { - } - - @BeforeAll - public static void setUpClass() { - try (InputStream is = ApolloCertificateTest.class.getClassLoader().getResourceAsStream("test_cert.pem")) { - acert = ApolloCertificate.loadPEMFromStream(is); - } catch (IOException ex) { - log.error("Can not load test certificate ", ex); - } catch (ApolloCertificateException ex) { - log.error("can not parse test certificate", ex); - } - } - - /** - * Test of getAuthorityId method, of class ApolloCertificate. - */ - @Test - public void testGetAuthorityId() { - AuthorityID result = acert.getAuthorityId(); - assertEquals(5139, result.getActorType()); - } - - /** - * Test of getCN method, of class ApolloCertificate. - */ - @Test - public void testGetCN() { - String result = acert.getCN(); - assertEquals("al.cn.ua", result); - } - - /** - * Test of getOrganization method, of class ApolloCertificate. - */ - @Test - public void testGetOrganization() { - String expResult = "FirstBridge"; - String result = acert.getOrganization(); - assertEquals(expResult, result); - } - - /** - * Test of getOrganizationUnit method, of class ApolloCertificate. - */ - @Test - public void testGetOrganizationUnit() { - String expResult = "FB-cn"; - String result = acert.getOrganizationUnit(); - assertEquals(expResult, result); - } - - /** - * Test of getCountry method, of class ApolloCertificate. - */ - @Test - public void testGetCountry() { - String expResult = "UA"; - String result = acert.getCountry(); - assertEquals(expResult, result); - } - - /** - * Test of getCity method, of class ApolloCertificate. - */ - @Test - public void testGetCity() { - String expResult = "Chernigiv"; - String result = acert.getCity(); - assertEquals(expResult, result); - } - - /** - * Test of getCertificatePurpose method, of class ApolloCertificate. - */ - @Test - public void testGetCertificatePurpose() { - String expResult = "Node"; - String result = acert.getCertificatePurpose(); - assertEquals(expResult, result); - } - - /** - * Test of getIPAddresses method, of class ApolloCertificate. - */ - @Test - public void testGetIPAddresses() { - List expResult = null; - List result = acert.getIPAddresses(); - assertEquals(expResult, result); - } - - /** - * Test of getDNSNames method, of class ApolloCertificate. - */ - @Test - public void testGetDNSNames() { - List expResult = null; - List result = acert.getDNSNames(); - assertEquals(expResult, result); - } - - /** - * Test of getStateOrProvince method, of class ApolloCertificate. - */ - @Test - public void testGetStateOrProvince() { - String expResult = null; - String result = acert.getStateOrProvince(); - assertEquals(expResult, result); - } - - /** - * Test of getEmail method, of class ApolloCertificate. - */ - @Test - public void testGetEmail() { - String expResult = "alukin@gmail.com"; - String result = acert.getEmail(); - assertEquals(expResult, result); - } - - /** - * Test of getPEM method, of class ApolloCertificate. - */ - @Test - public void testGetPEM() { - String result = acert.getPEM(); - assertEquals(true, result.startsWith("-----BEGIN CERTIFICATE----")); - } - - /** - * Test of isValid method, of class ApolloCertificate. - */ - @Test - public void testIsValid() { - Date date = null; - boolean expResult = false; - boolean result = acert.isValid(date); - assertEquals(expResult, result); - } - - /** - * Test of getSerial method, of class ApolloCertificate. - */ - @Test - public void testGetSerial() { - BigInteger result = acert.getSerial(); - BigInteger expResult = BigInteger.valueOf(1582313240538L); - assertEquals(expResult, result); - } - - @Test - public void testGetIssuerAttributes() { - CertAttributes cert_attr = acert.getIssuerAttrinutes(); - assertEquals("al.cn.ua", cert_attr.getCn()); - assertEquals("FirstBridge", cert_attr.getO()); - } - -} diff --git a/apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/ConfigDirProviderTest.java b/apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/ConfigDirProviderTest.java index 8eeaf7948c..6aa599706d 100644 --- a/apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/ConfigDirProviderTest.java +++ b/apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/ConfigDirProviderTest.java @@ -23,7 +23,7 @@ public class ConfigDirProviderTest { = System.getProperty("user.home") + File.separator + "." + APPLICATION_NAME + File.separator + "conf"; public static final String INSTALLATION_CONFIG_DIR = getInstallationConfigDir(); - public static final String SYSTEM_CONFIG_DIR = "/etc/" + APPLICATION_NAME + "/conf"; + public static final String SYSTEM_CONFIG_DIR = "/etc/" + APPLICATION_NAME + File.separator + "conf"; private static String getInstallationConfigDir() { try { diff --git a/apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/PathSpecificationTest.java b/apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/PathSpecificationTest.java deleted file mode 100644 index 5a4bf91865..0000000000 --- a/apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/supervisor/client/impl/PathSpecificationTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.apollocurrency.aplwallet.apl.util.supervisor.client.impl; - -import java.util.Map; -import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - -/** - * - * @author al - */ -public class PathSpecificationTest { - - public PathSpecificationTest() { - } - - - /** - * Test of fromSpecString method, of class PathSpecification. - */ - @Test - public void testFromSpecString() { - String pathSpec1 = "/test/one/{param1}/{param2}"; - PathSpecification result1 = PathSpecification.fromSpecString(pathSpec1); - - assertEquals("/test/one", result1.prefix); - assertEquals("param1", result1.paramNames.get(0)); - assertEquals("param2", result1.paramNames.get(1)); - - String pathSpec2 = "/test/two/one"; - PathSpecification result2 = PathSpecification.fromSpecString(pathSpec2); - - assertEquals("/test/two/one", result2.prefix); - assertEquals(0, result2.paramNames.size()); - - String pathSpec3 = "/test/one/{param1/{param2}"; - PathSpecification result3 = PathSpecification.fromSpecString(pathSpec3); - - assertEquals("/test/one", result3.prefix); - assertEquals("param1", result3.paramNames.get(0)); - assertEquals("param2", result3.paramNames.get(1)); - } - - /** - * Test of matches method, of class PathSpecification. - */ - @Test - public void testMatches() { - String pathSpec = "/test/one/{param1}/{param2}"; - PathSpecification ps = PathSpecification.fromSpecString(pathSpec); - boolean result1 = ps.matches("/test/one/1"); - assertEquals(true,result1); - boolean result2 = ps.matches("/test/one/1/2/3"); - assertEquals(true,result2); - } - - /** - * Test of parseParams method, of class PathSpecification. - */ - @Test - public void testParseParams() { - String pathSpec = "/test/one/{param1}/{param2}"; - PathSpecification ps = PathSpecification.fromSpecString(pathSpec); - Map params = ps.parseParams("/test/one/1"); - assertEquals("1", params.get("param1")); - assertEquals(null, params.get("param2")); - - Map params1 = ps.parseParams("/test/one/1/2"); - assertEquals("1", params1.get("param1")); - assertEquals("2", params1.get("param2")); - - Map params2 = ps.parseParams("test/one/1/2"); - assertEquals("1", params1.get("param1")); - assertEquals("2", params1.get("param2")); - } - -} diff --git a/apl-utils/src/test/resources/test_cert.pem b/apl-utils/src/test/resources/test_cert.pem deleted file mode 100644 index 3e67d7af97..0000000000 --- a/apl-utils/src/test/resources/test_cert.pem +++ /dev/null @@ -1,23 +0,0 @@ ------BEGIN CERTIFICATE----- -MIID5TCCA0agAwIBAgIGAXBpN/faMAoGCCqGSM49BAMEMIIBBDERMA8GA1UEAwwI -YWwuY24udWExEjAQBgNVBAcMCUNoZXJuaWdpdjEUMBIGA1UECgwLRmlyc3RCcmlk -Z2UxLzAtBgoJkiaJk/IsZAEBDB8wMDAyZGEwZTMyZTA3YjYxYzlmMDI1MWZlNjI3 -YTljMSkwJwYDVQQFEyAwMDAxZjFmY2Y4MmQxMzJmOWJiMDE4Y2E2NzM4YTE5ZjEO -MAwGA1UECwwFRkItY24xHzAdBgkqhkiG9w0BCQEWEGFsdWtpbkBnbWFpbC5jb20x -CzAJBgNVBAYTAlVBMSswKQYDVQQPDCIxNTE0MTMxMjExMTAwOTA4MDYwNzA2MDUw -NDAzMDIwMTAwMB4XDTIwMDIyMDE5MjcyMFoXDTIwMDIwNjAzNDUzMVowggEEMREw -DwYDVQQDDAhhbC5jbi51YTESMBAGA1UEBwwJQ2hlcm5pZ2l2MRQwEgYDVQQKDAtG -aXJzdEJyaWRnZTEvMC0GCgmSJomT8ixkAQEMHzAwMDJkYTBlMzJlMDdiNjFjOWYw -MjUxZmU2MjdhOWMxKTAnBgNVBAUTIDAwMDFmMWZjZjgyZDEzMmY5YmIwMThjYTY3 -MzhhMTlmMQ4wDAYDVQQLDAVGQi1jbjEfMB0GCSqGSIb3DQEJARYQYWx1a2luQGdt -YWlsLmNvbTELMAkGA1UEBhMCVUExKzApBgNVBA8MIjE1MTQxMzEyMTExMDA5MDgw -NjA3MDYwNTA0MDMwMjAxMDAwgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABAHDReX2 -jACnMlMwzEfrIqCD4UGRVJwQ3fi0UzayDAmWjrZ0pXqmcvI0DVBZfYHVJOhuD4za -bk8rusgKGESMqPDJjAH4Tq66MCk7eMpmiDlUg3nzBZ/IX57Iihph0vwyf+cc4SUC -H/9b1pUUL2XR6Ibhf6d91HunEIecbEv0AL4QvdjFJqNdMFswDgYDVR0PAQH/BAQD -AgSQMCoGA1UdJQEB/wQgMB4GCCsGAQUFBwMDBggrBgEFBQcDCAYIKwYBBQUHAwQw -DwYDVR0TAQH/BAUwAwEB/zAMBgNVHREBAf8EAjAAMAoGCCqGSM49BAMEA4GMADCB -iAJCALefzX2CR1Xog4sfb+6W5yNw9W/81uvFARF7dD0lE/eQVM+0vz/Fq74GGzao -bpsSO4YzEG0GGYFmotaPMQKnCoxaAkIBkGiNy4vggD47S+fEHNrUDrqiAFuTg3LW -Vl2S882/PjG9J0HSWv2d53xqOGDxR/RV6LjLrVxbSI9P49YNbGtpRLw= ------END CERTIFICATE----- diff --git a/apl-utils/src/test/resources/test_cert_pvtkey.pem b/apl-utils/src/test/resources/test_cert_pvtkey.pem deleted file mode 100644 index 422f918ec1..0000000000 --- a/apl-utils/src/test/resources/test_cert_pvtkey.pem +++ /dev/null @@ -1,8 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIH3AgEAMBAGByqGSM49AgEGBSuBBAAjBIHfMIHcAgEBBEIBwfyQxUSPOpP/hno2 -GS9e+yJFCcGUCpTNMHlQQbOKgwOspAiRSSNt1jzoRW6j0Fo++Z04wSrFWJA0wsvH -6XU3khugBwYFK4EEACOhgYkDgYYABAHDReX2jACnMlMwzEfrIqCD4UGRVJwQ3fi0 -UzayDAmWjrZ0pXqmcvI0DVBZfYHVJOhuD4zabk8rusgKGESMqPDJjAH4Tq66MCk7 -eMpmiDlUg3nzBZ/IX57Iihph0vwyf+cc4SUCH/9b1pUUL2XR6Ibhf6d91HunEIec -bEv0AL4QvdjFJg== ------END PRIVATE KEY----- diff --git a/apl-vault-wallet/src/main/resources/META-INF/beans.xml b/apl-vault-wallet/src/main/resources/META-INF/beans.xml index 542bd53ab6..0178091e87 100644 --- a/apl-vault-wallet/src/main/resources/META-INF/beans.xml +++ b/apl-vault-wallet/src/main/resources/META-INF/beans.xml @@ -1,5 +1,14 @@ \ No newline at end of file + version="1.1" bean-discovery-mode="all"> + + org.jboss.weld.environment.se.threading.RunnableDecorator + + + + + + \ No newline at end of file diff --git a/conf/CA-certs/ApolloWallet-root.crt b/conf/CA-certs/ApolloWallet-root.crt new file mode 100644 index 0000000000..ba321bdbd4 --- /dev/null +++ b/conf/CA-certs/ApolloWallet-root.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFMjCCBJOgAwIBAgIIEL8TEjSqgtkwCgYIKoZIzj0EAwQwggFCMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCTUkxFTATBgNVBAcTDE1vdW50IFZlcm5vbjEZMBcGA1UE +ChMQQXBvbGxvV2FsbGV0Lm9yZzENMAsGA1UECxMEQ2VydDEeMBwGA1UEAxMVUm9v +dC5BcG9sbG93YWxsZXQub3JnMSQwIgYJKoZIhvcNAQkBFhVjZXJ0QGFwb2xsb3dh +bGxldC5vcmcxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJNSTEVMBMGA1UEBxMMTW91 +bnQgVmVybm9uMRkwFwYDVQQKExBBcG9sbG9XYWxsZXQub3JnMQ0wCwYDVQQLEwRD +ZXJ0MR4wHAYDVQQDExVSb290LkFwb2xsb1dhbGxldC5vcmcxJDAiBgkqhkiG9w0B +CQEWFWNlcnRAYXBvbGxvd2FsbGV0Lm9yZzAeFw0yMDA5MDUxODI2MDBaFw00MDA5 +MDUxODI2MDBaMIIBQjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk1JMRUwEwYDVQQH +EwxNb3VudCBWZXJub24xGTAXBgNVBAoTEEFwb2xsb1dhbGxldC5vcmcxDTALBgNV +BAsTBENlcnQxHjAcBgNVBAMTFVJvb3QuQXBvbGxvd2FsbGV0Lm9yZzEkMCIGCSqG +SIb3DQEJARYVY2VydEBhcG9sbG93YWxsZXQub3JnMQswCQYDVQQGEwJVUzELMAkG +A1UECBMCTUkxFTATBgNVBAcTDE1vdW50IFZlcm5vbjEZMBcGA1UEChMQQXBvbGxv +V2FsbGV0Lm9yZzENMAsGA1UECxMEQ2VydDEeMBwGA1UEAxMVUm9vdC5BcG9sbG9X +YWxsZXQub3JnMSQwIgYJKoZIhvcNAQkBFhVjZXJ0QGFwb2xsb3dhbGxldC5vcmcw +gZswEAYHKoZIzj0CAQYFK4EEACMDgYYABAAVG2rKuZhN4YkbUcg910pXCjxEBtVQ +5XzcI4fnLDRm0BV1Lea8iwj8spY+V4SEtwbzV3yYfNt6SUiQuaXB9JER1QEgikea +01J6vrooEesu9iIf30UV1+s6bcQ8eqMZRjqyP/0PpRyJhswoSCosJlo9Cb9rzOQg +p1G0A+UVpxLpWRbm+qOCASowggEmMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FN25ljt/mV1xBsZpFuKyBHUKFNnPMB8GA1UdIwQYMBaAFN25ljt/mV1xBsZpFuKy +BHUKFNnPMA4GA1UdDwEB/wQEAwIBBjAgBgNVHSUBAf8EFjAUBggrBgEFBQcDAwYI +KwYBBQUHAwkwIAYDVR0RBBkwF4IVUm9vdC5BcG9sbG93YWxsZXQub3JnMCUGA1Ud +EgQeMByCGlJvb3QuY2VydC5BcG9sbG93YWxsZXQub3JnMCUGA1UdHwQeMBwwGqAY +oBaCFGNybC5hcG9sbG93YWxsZXQub3JnMBEGCWCGSAGG+EIBAQQEAwIABzAeBglg +hkgBhvhCAQ0EERYPeGNhIGNlcnRpZmljYXRlMAoGCCqGSM49BAMEA4GMADCBiAJC +ATllB6P+gtdryutXwe5yKVvGwJyFZ++M4P0s/lhBcRJPX1ESEnGN6U/XBssaDFR6 +l07jGJxutBY+Tt5s81H7sxD+AkIBEk0Y/UfUqJor3WHc/D5TNkChfvppgh8PCZyT +3E3o8Gw1/64nDAUyNoUzoElTDfFei8KkC+bA+zjx1MQicGM7ZAY= +-----END CERTIFICATE-----