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
11 changes: 11 additions & 0 deletions QORTIUM-CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ own chain.

## Change Entries

### 2026-07-20 - qdn: make QDN relaying unconditional

Removes the inherited operator switch that allowed a QDN-enabled node to opt out
of relaying discovery, metadata, and chunks for other peers. QDN-enabled Qortium
nodes now always participate in relay while retaining separate storage-policy,
block-list, capacity, hop/time, and queue controls. Existing settings files that
still contain `relayModeEnabled` remain loadable, but the value is ignored; the
setting is no longer writable or shipped in Previewnet templates. The legacy
`/arbitrary/relaymode` endpoint remains temporarily for compatibility and
always returns `true`.

### 2026-07-19 - fix(qdn): honor identifiers on status query requests

Makes the shorter QDN status endpoint honor an `identifier` query
Expand Down
1 change: 0 additions & 1 deletion preview/settings-preview-seed-netcup.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@
"recoveryModeTimeout": 0,
"autoUpdateMode": "OFF",
"qdnEnabled": true,
"relayModeEnabled": true,
"qdnAuthBypassEnabled": true,
"gatewayEnabled": true,
"gatewayPort": 8090,
Expand Down
1 change: 0 additions & 1 deletion preview/settings-preview-seed.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@
"recoveryModeTimeout": 0,
"autoUpdateMode": "OFF",
"qdnEnabled": true,
"relayModeEnabled": true,
"qdnAuthBypassEnabled": true,
"gatewayEnabled": true,
"gatewayPort": 8090,
Expand Down
1 change: 0 additions & 1 deletion preview/settings-preview.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@
"recoveryModeTimeout": 0,
"autoUpdateMode": "NOTIFY",
"qdnEnabled": true,
"relayModeEnabled": true,
"qdnAuthBypassEnabled": true,
"publicQdnPublishMaxSize": 104857600,
"publicApiWriteMaxBodySize": 262144,
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/org/qortium/api/resource/ArbitraryResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,9 @@ public String createArbitrary(ArbitraryTransactionData transactionData) {
@GET
@Path("/relaymode")
@Operation(
summary = "Returns whether relay mode is enabled or not",
summary = "Returns true because QDN relay is always enabled",
description = "Deprecated compatibility endpoint. QDN-enabled Qortium nodes always relay QDN data.",
deprecated = true,
responses = {
@ApiResponse(
content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "boolean"))
Expand All @@ -631,7 +633,7 @@ public String createArbitrary(ArbitraryTransactionData transactionData) {
public boolean getRelayMode(@HeaderParam(Security.API_KEY_HEADER) String apiKey) {
Security.checkApiCallAllowed(request);

return Settings.getInstance().isRelayModeEnabled();
return true;
}

@GET
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,9 @@ public class ArbitraryDataFileListManager {
/** Maximum number of hops that a file list relay request is allowed to make */
public static int RELAY_REQUEST_MAX_HOPS = 4; // was 4, this is no longer ArbData, only metaData/Lists
public static int SEARCH_DEPTH_MAX_HOPS = 6; // Only used to determine if we should forward or terminate a search for QDN data
private final Boolean isRelayAvailable;

private ArbitraryDataFileListManager() {
getArbitraryDataFileListMessageScheduler.scheduleAtFixedRate(this::processNetworkGetArbitraryDataFileListMessage, 60 * 1000, 500, TimeUnit.MILLISECONDS);
arbitraryDataFileListMessageScheduler.scheduleAtFixedRate(this::processNetworkArbitraryDataFileListMessage, 60 * 1000, 500, TimeUnit.MILLISECONDS);
this.isRelayAvailable = Settings.getInstance().isRelayModeEnabled();
}


Expand Down Expand Up @@ -551,14 +548,18 @@ public void onNetworkArbitraryDataFileListMessage(Peer peer, Message message) {
* Received a ArbitraryDataList Message
*/
private void processNetworkArbitraryDataFileListMessage() {
List<PeerMessage> messagesToProcess;
synchronized (arbitraryDataFileListMessageLock) {
messagesToProcess = new ArrayList<>(arbitraryDataFileListMessageList);
arbitraryDataFileListMessageList.clear();
}

try {
List<PeerMessage> messagesToProcess;
synchronized (arbitraryDataFileListMessageLock) {
messagesToProcess = new ArrayList<>(arbitraryDataFileListMessageList);
arbitraryDataFileListMessageList.clear();
}
processNetworkArbitraryDataFileListMessages(messagesToProcess);
}

/** Synchronous processing seam used by the scheduler and relay-behavior tests. */
void processNetworkArbitraryDataFileListMessages(List<PeerMessage> messagesToProcess) {
try {
if (messagesToProcess.isEmpty()) return;

// Store ALL peer messages per signature (not just the last one)
Expand Down Expand Up @@ -662,7 +663,8 @@ private void processNetworkArbitraryDataFileListMessage() {

// Determine how many peers to process based on request type
List<PeerMessage> peersToProcess;
if (isRelayRequest != null && isRelayRequest && this.isRelayAvailable) {
boolean relayRequest = Boolean.TRUE.equals(isRelayRequest);
if (relayRequest) {
// For relay requests, only process first peer to avoid duplicate forwards
peersToProcess = Collections.singletonList(peerMessages.get(0));

Expand All @@ -680,7 +682,7 @@ private void processNetworkArbitraryDataFileListMessage() {
ArbitraryDataFileListMessage arbitraryDataFileListMessage = (ArbitraryDataFileListMessage) message;

// Process direct download responses (not relay forwarding)
if (!isRelayRequest || !this.isRelayAvailable) {
if (!relayRequest) {

Long now = NTP.getTime();

Expand Down Expand Up @@ -769,7 +771,7 @@ private void processNetworkArbitraryDataFileListMessage() {

// Forwarding - We are not the original requestor, just in the middle
LOGGER.trace("Status of isRelayRequest {}", isRelayRequest);
if (isRelayRequest && this.isRelayAvailable) {
if (relayRequest) {
Triple<String, Peer, Long> request = requestBySignature58.get(signature58);
Peer requestingPeer = request.getB();
if (requestingPeer != null) {
Expand Down Expand Up @@ -1064,7 +1066,7 @@ private void processNetworkGetArbitraryDataFileListMessage() {

String nodeId = NetworkData.getInstance().getOurNodeId();
arbitraryDataFileListMessage = new ArbitraryDataFileListMessage(signature,
hashes, NTP.getTime(), 0, ourAddress, nodeId, this.isRelayAvailable, this.getIsDirectConnectable());
hashes, NTP.getTime(), 0, ourAddress, nodeId, true, this.getIsDirectConnectable());

arbitraryDataFileListMessage.setId(message.getId());

Expand Down Expand Up @@ -1092,11 +1094,8 @@ private void processNetworkGetArbitraryDataFileListMessage() {
}
}

LOGGER.trace("We don't have hashes or all hashes - Checking Relay Mode");
// We may need to forward this request on

//if (this.isRelayAvailable ) { = We do not want to block the relay of file find requests, this prevents Direct-Connect finding
// In relay mode - so ask our other peers if they have it
LOGGER.trace("We don't have hashes or all hashes - forwarding the QDN search");
// QDN-enabled Qortium nodes always relay discovery requests.

GetArbitraryDataFileListMessage getArbitraryDataFileListMessage = (GetArbitraryDataFileListMessage) message;

Expand Down Expand Up @@ -1135,9 +1134,6 @@ private void processNetworkGetArbitraryDataFileListMessage() {
} else {
LOGGER.trace("Relay Request has timed out");
}
//} else {
// LOGGER.debug("Relay (fetch-reserve) is disabled");
//}
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
Expand Down
Loading
Loading