From 4c020819926c21a0eef54020c1cfb833f1b0d941 Mon Sep 17 00:00:00 2001 From: catbref Date: Mon, 21 Feb 2022 20:05:29 +0000 Subject: [PATCH] Tidy up TradeBot presence logging. Decorate API endpoints /crosschain/tradeoffers and /crosschain/trade with presence expiry timestamps --- .../api/resource/CrossChainResource.java | 12 +++++++- .../qortal/controller/tradebot/TradeBot.java | 30 +++++++++++++++---- .../data/crosschain/CrossChainTradeData.java | 6 ++++ .../qortal/data/network/OnlineTradeData.java | 12 ++++++++ 4 files changed, 53 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/qortal/api/resource/CrossChainResource.java b/src/main/java/org/qortal/api/resource/CrossChainResource.java index 47eee301..bb7c70a5 100644 --- a/src/main/java/org/qortal/api/resource/CrossChainResource.java +++ b/src/main/java/org/qortal/api/resource/CrossChainResource.java @@ -25,6 +25,7 @@ import org.qortal.api.ApiExceptionFactory; import org.qortal.api.Security; import org.qortal.api.model.CrossChainCancelRequest; import org.qortal.api.model.CrossChainTradeSummary; +import org.qortal.controller.tradebot.TradeBot; import org.qortal.crosschain.SupportedBlockchain; import org.qortal.crosschain.ACCT; import org.qortal.crosschain.AcctMode; @@ -120,6 +121,8 @@ public class CrossChainResource { crossChainTrades = crossChainTrades.subList(0, upperLimit); } + crossChainTrades.stream().forEach(CrossChainResource::decorateTradeDataWithPresence); + return crossChainTrades; } catch (DataException e) { throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); @@ -151,7 +154,11 @@ public class CrossChainResource { if (acct == null) throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); - return acct.populateTradeData(repository, atData); + CrossChainTradeData crossChainTradeData = acct.populateTradeData(repository, atData); + + decorateTradeDataWithPresence(crossChainTradeData); + + return crossChainTradeData; } catch (DataException e) { throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); } @@ -486,4 +493,7 @@ public class CrossChainResource { } } + private static void decorateTradeDataWithPresence(CrossChainTradeData crossChainTradeData) { + TradeBot.getInstance().decorateTradeDataWithPresence(crossChainTradeData); + } } diff --git a/src/main/java/org/qortal/controller/tradebot/TradeBot.java b/src/main/java/org/qortal/controller/tradebot/TradeBot.java index 88c720b2..9182ff6e 100644 --- a/src/main/java/org/qortal/controller/tradebot/TradeBot.java +++ b/src/main/java/org/qortal/controller/tradebot/TradeBot.java @@ -346,7 +346,7 @@ public class TradeBot implements Listener { } if (removedCount > 0) - LOGGER.trace("Removed {} old online trade signatures", removedCount); + LOGGER.debug("Removed {} old online trade signatures", removedCount); } /*package*/ void updatePresence(Repository repository, TradeBotData tradeBotData, CrossChainTradeData tradeData) @@ -411,7 +411,7 @@ public class TradeBot implements Listener { this.pendingOnlineSignatures.clear(); } - LOGGER.trace("Broadcasting {} new online trades", safeOnlineSignatures.size()); + LOGGER.debug("Broadcasting {} new online trades", safeOnlineSignatures.size()); OnlineTradesMessage onlineTradesMessage = new OnlineTradesMessage(safeOnlineSignatures); Network.getInstance().broadcast(peer -> onlineTradesMessage); @@ -431,7 +431,7 @@ public class TradeBot implements Listener { if (safeOnlineSignatures.isEmpty()) return; - LOGGER.trace("Broadcasting all {} known online trades. Next broadcast timestamp: {}", + LOGGER.debug("Broadcasting all {} known online trades. Next broadcast timestamp: {}", safeOnlineSignatures.size(), nextBroadcastTimestamp ); @@ -458,8 +458,11 @@ public class TradeBot implements Listener { entriesUnknownToPeer.remove(pubkeyByteArray); } - LOGGER.trace("Sending {} known \\ {} peers = {} online trades to peer {}", - knownCount, peersOnlineTrades.size(), entriesUnknownToPeer.size() + if (entriesUnknownToPeer.isEmpty()) + return; + + LOGGER.debug("Sending {} online trades to peer {} after excluding their {} from known {}", + entriesUnknownToPeer.size(), peer, peersOnlineTrades.size(), knownCount ); // Send complement to peer @@ -567,7 +570,7 @@ public class TradeBot implements Listener { } // Convert signer's public key to address form - String signerAddress = Crypto.toAddress(publicKey); + String signerAddress = peersOnlineTrade.getTradeAddress(); // Signer's public key (in address form) must match Bob's / Alice's trade public key (in address form) if (!signerAddress.equals(tradeData.qortalCreatorTradeAddress) && !signerAddress.equals(tradeData.qortalPartnerAddress)) { @@ -609,4 +612,19 @@ public class TradeBot implements Listener { rebuildSafeAllOnline(); } } + + public void decorateTradeDataWithPresence(CrossChainTradeData crossChainTradeData) { + // Match by AT address, then check for Bob vs Alice + this.safeAllOnlineByPubkey.values().stream() + .filter(onlineTradeData -> onlineTradeData.getAtAddress().equals(crossChainTradeData.qortalAtAddress)) + .forEach(onlineTradeData -> { + String signerAddress = onlineTradeData.getTradeAddress(); + + // Signer's public key (in address form) must match Bob's / Alice's trade public key (in address form) + if (signerAddress.equals(crossChainTradeData.qortalCreatorTradeAddress)) + crossChainTradeData.creatorPresenceExpiry = onlineTradeData.getTimestamp(); + else if (signerAddress.equals(crossChainTradeData.qortalPartnerAddress)) + crossChainTradeData.partnerPresenceExpiry = onlineTradeData.getTimestamp(); + }); + } } diff --git a/src/main/java/org/qortal/data/crosschain/CrossChainTradeData.java b/src/main/java/org/qortal/data/crosschain/CrossChainTradeData.java index 69250e54..edc115b6 100644 --- a/src/main/java/org/qortal/data/crosschain/CrossChainTradeData.java +++ b/src/main/java/org/qortal/data/crosschain/CrossChainTradeData.java @@ -94,6 +94,12 @@ public class CrossChainTradeData { public String acctName; + @Schema(description = "Timestamp when AT creator's trade-bot presence expires") + public Long creatorPresenceExpiry; + + @Schema(description = "Timestamp when trade partner's trade-bot presence expires") + public Long partnerPresenceExpiry; + // Constructors // Necessary for JAXB diff --git a/src/main/java/org/qortal/data/network/OnlineTradeData.java b/src/main/java/org/qortal/data/network/OnlineTradeData.java index 102030e1..1ae48718 100644 --- a/src/main/java/org/qortal/data/network/OnlineTradeData.java +++ b/src/main/java/org/qortal/data/network/OnlineTradeData.java @@ -1,5 +1,7 @@ package org.qortal.data.network; +import org.qortal.crypto.Crypto; + import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import java.util.Arrays; @@ -12,6 +14,7 @@ public class OnlineTradeData { protected byte[] publicKey; // Could be BOB's or ALICE's protected byte[] signature; // Not always present protected String atAddress; // Not always present + protected String tradeAddress; // Lazily instantiated // Constructors @@ -46,6 +49,15 @@ public class OnlineTradeData { return this.atAddress; } + // Probably don't need synchronization + public String getTradeAddress() { + if (tradeAddress != null) + return tradeAddress; + + tradeAddress = Crypto.toAddress(this.publicKey); + return tradeAddress; + } + // Comparison @Override