Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions QORTIUM-CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ own chain.

## Change Entries

### 2026-06-02 - Refresh tray sync progress from peer height

Changed the tray tooltip so its syncing percentage and blocks-remaining count use the same current peer-height progress calculation as the node status API. This keeps the desktop tooltip moving while a preview node catches up, instead of leaving an older remaining-block estimate visible after the local height has advanced.

### 2026-06-02 - Expose preview peer reachability diagnostics

Added inbound and outbound peer counts plus P2P and QDN reachability flags to the node status response so preview testers can tell the difference between outbound-only connectivity and public reachability. Preview participants now target four outbound chain peers when enough reachable peers are available, and the preview docs explain how firewall or router forwarding affects peer counts.
Expand Down
34 changes: 28 additions & 6 deletions src/main/java/org/qortium/controller/Controller.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.qortium.api.ApiService;
import org.qortium.api.DomainMapService;
import org.qortium.api.GatewayService;
import org.qortium.api.model.NodeStatus;
import org.qortium.api.resource.TransactionsResource;
import org.qortium.block.Block;
import org.qortium.block.BlockChain;
Expand Down Expand Up @@ -1104,7 +1105,8 @@ public void updateSysTray() {
return;
}

final int numberOfPeers = Network.getInstance().getImmutableHandshakedPeers().size();
final List<Peer> handshakedPeers = Network.getInstance().getImmutableHandshakedPeers();
final int numberOfPeers = handshakedPeers.size();

final int height = getChainHeight();

Expand All @@ -1117,9 +1119,14 @@ public void updateSysTray() {
// Any block in the last 2 hours is considered "up to date" for the purposes of displaying statuses.
// This also aligns with the time interval required for continued online account submission.
final Long minLatestBlockTimestamp = NTP.getTime() - (2 * 60 * 60 * 1000L);
final boolean isUpToDate = this.isUpToDate(minLatestBlockTimestamp);
final NodeStatus.SyncProgress syncProgress = NodeStatus.calculateSyncProgress(height,
Synchronizer.getInstance().getSyncTargetHeight(), Synchronizer.getInstance().isSynchronizing(),
getBestPeerHeight(handshakedPeers), isUpToDate, Settings.getInstance().isLite(), numberOfPeers,
Settings.getInstance().getMinBlockchainPeers());

// Only show sync percent if it's less than 100, to avoid confusion
final Integer syncPercent = Synchronizer.getInstance().getSyncPercent();
final Integer syncPercent = syncProgress.syncPercent;
final boolean isSyncing = (syncPercent != null && syncPercent < 100);

synchronized (Synchronizer.getInstance().syncLock) {
Expand All @@ -1131,11 +1138,11 @@ else if (numberOfPeers < Settings.getInstance().getMinBlockchainPeers()) {
actionText = Translator.INSTANCE.translate("SysTray", "CONNECTING");
nodeTray.setTrayIcon(TrayIconState.SYNCHRONIZING);
}
else if (!this.isUpToDate(minLatestBlockTimestamp) && isSyncing) {
actionText = String.format("%s - %d%%", Translator.INSTANCE.translate("SysTray", "SYNCHRONIZING_BLOCKCHAIN"), Synchronizer.getInstance().getSyncPercent());
else if (!isUpToDate && isSyncing) {
actionText = String.format("%s - %d%%", Translator.INSTANCE.translate("SysTray", "SYNCHRONIZING_BLOCKCHAIN"), syncPercent);
nodeTray.setTrayIcon(TrayIconState.SYNCHRONIZING);
}
else if (!this.isUpToDate(minLatestBlockTimestamp)) {
else if (!isUpToDate) {
actionText = String.format("%s", Translator.INSTANCE.translate("SysTray", "SYNCHRONIZING_BLOCKCHAIN"));
nodeTray.setTrayIcon(TrayIconState.SYNCHRONIZING);
}
Expand All @@ -1153,7 +1160,7 @@ else if (OnlineAccountsManager.getInstance().hasActiveOnlineAccountSignatures())
if (!Settings.getInstance().isLite()) {
tooltip = tooltip.concat(String.format(" - %s %d", heightText, height));

final Integer blocksRemaining = Synchronizer.getInstance().getBlocksRemaining();
final Integer blocksRemaining = syncProgress.syncBlocksRemaining;
if (blocksRemaining != null && blocksRemaining > 0) {
String blocksRemainingText = Translator.INSTANCE.translate("SysTray", "BLOCKS_REMAINING");
tooltip = tooltip.concat(String.format(" - %d %s", blocksRemaining, blocksRemainingText));
Expand All @@ -1167,6 +1174,21 @@ else if (OnlineAccountsManager.getInstance().hasActiveOnlineAccountSignatures())
});
}

private static Integer getBestPeerHeight(List<Peer> peers) {
Integer bestPeerHeight = null;

for (Peer peer : peers) {
BlockSummaryData chainTipData = peer.getChainTipData();
if (chainTipData == null)
continue;

if (bestPeerHeight == null || chainTipData.getHeight() > bestPeerHeight)
bestPeerHeight = chainTipData.getHeight();
}

return bestPeerHeight;
}

public void deleteExpiredTransactions() {
final Long now = NTP.getTime();
if (now == null)
Expand Down