Merge remote-tracking branch 'qortal-data/master' into qdn

This commit is contained in:
CalDescent 2022-01-09 21:10:48 +00:00
commit f9749cd82c
10 changed files with 56 additions and 30 deletions

View File

@ -137,10 +137,7 @@ public class AdminResource {
) )
} }
) )
@SecurityRequirement(name = "apiKey")
public NodeStatus status() { public NodeStatus status() {
Security.checkApiCallAllowed(request);
NodeStatus nodeStatus = new NodeStatus(); NodeStatus nodeStatus = new NodeStatus();
return nodeStatus; return nodeStatus;
@ -252,9 +249,7 @@ public class AdminResource {
} }
) )
@ApiErrors({ApiError.REPOSITORY_ISSUE}) @ApiErrors({ApiError.REPOSITORY_ISSUE})
@SecurityRequirement(name = "apiKey")
public List<MintingAccountData> getMintingAccounts() { public List<MintingAccountData> getMintingAccounts() {
Security.checkApiCallAllowed(request);
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
List<MintingAccountData> mintingAccounts = repository.getAccountRepository().getMintingAccounts(); List<MintingAccountData> mintingAccounts = repository.getAccountRepository().getMintingAccounts();
@ -751,4 +746,22 @@ public class AdminResource {
return apiKey.toString(); return apiKey.toString();
} }
@GET
@Path("/apikey/test")
@Operation(
summary = "Test an API key",
responses = {
@ApiResponse(
description = "true if authenticated",
content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "boolean"))
)
}
)
@SecurityRequirement(name = "apiKey")
public String testApiKey() {
Security.checkApiCallAllowed(request);
return "true";
}
} }

View File

@ -352,10 +352,7 @@ public class PeersResource {
) )
} }
) )
@SecurityRequirement(name = "apiKey")
public PeersSummary peersSummary() { public PeersSummary peersSummary() {
Security.checkApiCallAllowed(request);
PeersSummary peersSummary = new PeersSummary(); PeersSummary peersSummary = new PeersSummary();
List<Peer> connectedPeers = Network.getInstance().getConnectedPeers().stream().collect(Collectors.toList()); List<Peer> connectedPeers = Network.getInstance().getConnectedPeers().stream().collect(Collectors.toList());

View File

@ -159,7 +159,7 @@ public class ArbitraryDataFileManager {
// but only if these files are in accordance with our storage policy // but only if these files are in accordance with our storage policy
if (ArbitraryDataStorageManager.getInstance().canStoreData(arbitraryTransactionData)) { if (ArbitraryDataStorageManager.getInstance().canStoreData(arbitraryTransactionData)) {
// Use a null peer address to indicate our own // Use a null peer address to indicate our own
Message newArbitrarySignatureMessage = new ArbitrarySignaturesMessage(null, Arrays.asList(signature)); Message newArbitrarySignatureMessage = new ArbitrarySignaturesMessage(null, 0, Arrays.asList(signature));
Network.getInstance().broadcast(broadcastPeer -> newArbitrarySignatureMessage); Network.getInstance().broadcast(broadcastPeer -> newArbitrarySignatureMessage);
} }
} }

View File

@ -43,6 +43,9 @@ public class ArbitraryDataManager extends Thread {
/** Maximum time to hold information about an in-progress relay */ /** Maximum time to hold information about an in-progress relay */
public static final long ARBITRARY_RELAY_TIMEOUT = 30 * 1000L; // ms public static final long ARBITRARY_RELAY_TIMEOUT = 30 * 1000L; // ms
/** Maximum number of hops that an arbitrary signatures request is allowed to make */
private static int ARBITRARY_SIGNATURES_REQUEST_MAX_HOPS = 3;
private static ArbitraryDataManager instance; private static ArbitraryDataManager instance;
private final Object peerDataLock = new Object(); private final Object peerDataLock = new Object();
@ -99,7 +102,7 @@ public class ArbitraryDataManager extends Thread {
// Fetch data according to storage policy // Fetch data according to storage policy
switch (Settings.getInstance().getStoragePolicy()) { switch (Settings.getInstance().getStoragePolicy()) {
case FOLLOWED: case FOLLOWED:
case FOLLOWED_AND_VIEWED: case FOLLOWED_OR_VIEWED:
this.processNames(); this.processNames();
break; break;
@ -369,7 +372,7 @@ public class ArbitraryDataManager extends Thread {
// Broadcast the list, using null to represent our peer address // Broadcast the list, using null to represent our peer address
LOGGER.info("Broadcasting list of hosted signatures..."); LOGGER.info("Broadcasting list of hosted signatures...");
Message arbitrarySignatureMessage = new ArbitrarySignaturesMessage(null, hostedSignatures); Message arbitrarySignatureMessage = new ArbitrarySignaturesMessage(null, 0, hostedSignatures);
Network.getInstance().broadcast(broadcastPeer -> arbitrarySignatureMessage); Network.getInstance().broadcast(broadcastPeer -> arbitrarySignatureMessage);
} catch (DataException e) { } catch (DataException e) {
@ -429,8 +432,12 @@ public class ArbitraryDataManager extends Thread {
// If at least one signature in this batch was new to us, we should rebroadcast the message to the // If at least one signature in this batch was new to us, we should rebroadcast the message to the
// network in case some peers haven't received it yet // network in case some peers haven't received it yet
if (containsNewEntry) { if (containsNewEntry) {
LOGGER.debug("Rebroadcasting arbitrary signature list for peer {}", peerAddress); int requestHops = arbitrarySignaturesMessage.getRequestHops();
Network.getInstance().broadcast(broadcastPeer -> broadcastPeer == peer ? null : arbitrarySignaturesMessage); arbitrarySignaturesMessage.setRequestHops(++requestHops);
if (requestHops < ARBITRARY_SIGNATURES_REQUEST_MAX_HOPS) {
LOGGER.debug("Rebroadcasting arbitrary signature list for peer {}", peerAddress);
Network.getInstance().broadcast(broadcastPeer -> broadcastPeer == peer ? null : arbitrarySignaturesMessage);
}
} else { } else {
// Don't rebroadcast as otherwise we could get into a loop // Don't rebroadcast as otherwise we could get into a loop
} }

View File

@ -26,7 +26,7 @@ import java.util.stream.Collectors;
public class ArbitraryDataStorageManager extends Thread { public class ArbitraryDataStorageManager extends Thread {
public enum StoragePolicy { public enum StoragePolicy {
FOLLOWED_AND_VIEWED, FOLLOWED_OR_VIEWED,
FOLLOWED, FOLLOWED,
VIEWED, VIEWED,
ALL, ALL,
@ -126,7 +126,7 @@ public class ArbitraryDataStorageManager extends Thread {
// Check if our storage policy and and lists allow us to host data for this name // Check if our storage policy and and lists allow us to host data for this name
switch (Settings.getInstance().getStoragePolicy()) { switch (Settings.getInstance().getStoragePolicy()) {
case FOLLOWED_AND_VIEWED: case FOLLOWED_OR_VIEWED:
case ALL: case ALL:
case VIEWED: case VIEWED:
// If the policy includes viewed data, we can host it as long as it's not blocked // If the policy includes viewed data, we can host it as long as it's not blocked
@ -189,7 +189,7 @@ public class ArbitraryDataStorageManager extends Thread {
switch (Settings.getInstance().getStoragePolicy()) { switch (Settings.getInstance().getStoragePolicy()) {
case FOLLOWED: case FOLLOWED:
case FOLLOWED_AND_VIEWED: case FOLLOWED_OR_VIEWED:
return this.isFollowingName(name); return this.isFollowingName(name);
case ALL: case ALL:
@ -217,7 +217,7 @@ public class ArbitraryDataStorageManager extends Thread {
case NONE: case NONE:
case VIEWED: case VIEWED:
case FOLLOWED: case FOLLOWED:
case FOLLOWED_AND_VIEWED: case FOLLOWED_OR_VIEWED:
default: default:
return false; return false;
} }

View File

@ -2,7 +2,6 @@ package org.qortal.network.message;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import org.qortal.data.network.PeerData; import org.qortal.data.network.PeerData;
import org.qortal.transaction.DeployAtTransaction;
import org.qortal.transform.TransformationException; import org.qortal.transform.TransformationException;
import org.qortal.transform.Transformer; import org.qortal.transform.Transformer;
import org.qortal.utils.Serialization; import org.qortal.utils.Serialization;
@ -19,16 +18,18 @@ public class ArbitrarySignaturesMessage extends Message {
private static final int SIGNATURE_LENGTH = Transformer.SIGNATURE_LENGTH; private static final int SIGNATURE_LENGTH = Transformer.SIGNATURE_LENGTH;
private String peerAddress; private String peerAddress;
private int requestHops;
private List<byte[]> signatures; private List<byte[]> signatures;
public ArbitrarySignaturesMessage(String peerAddress, List<byte[]> signatures) { public ArbitrarySignaturesMessage(String peerAddress, int requestHops, List<byte[]> signatures) {
this(-1, peerAddress, signatures); this(-1, peerAddress, requestHops, signatures);
} }
private ArbitrarySignaturesMessage(int id, String peerAddress, List<byte[]> signatures) { private ArbitrarySignaturesMessage(int id, String peerAddress, int requestHops, List<byte[]> signatures) {
super(id, MessageType.ARBITRARY_SIGNATURES); super(id, MessageType.ARBITRARY_SIGNATURES);
this.peerAddress = peerAddress; this.peerAddress = peerAddress;
this.requestHops = requestHops;
this.signatures = signatures; this.signatures = signatures;
} }
@ -40,9 +41,19 @@ public class ArbitrarySignaturesMessage extends Message {
return this.signatures; return this.signatures;
} }
public int getRequestHops() {
return this.requestHops;
}
public void setRequestHops(int requestHops) {
this.requestHops = requestHops;
}
public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException, TransformationException { public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException, TransformationException {
String peerAddress = Serialization.deserializeSizedString(bytes, PeerData.MAX_PEER_ADDRESS_SIZE); String peerAddress = Serialization.deserializeSizedString(bytes, PeerData.MAX_PEER_ADDRESS_SIZE);
int requestHops = bytes.getInt();
int signatureCount = bytes.getInt(); int signatureCount = bytes.getInt();
if (bytes.remaining() != signatureCount * SIGNATURE_LENGTH) if (bytes.remaining() != signatureCount * SIGNATURE_LENGTH)
@ -55,7 +66,7 @@ public class ArbitrarySignaturesMessage extends Message {
signatures.add(signature); signatures.add(signature);
} }
return new ArbitrarySignaturesMessage(id, peerAddress, signatures); return new ArbitrarySignaturesMessage(id, peerAddress, requestHops, signatures);
} }
@Override @Override
@ -65,6 +76,8 @@ public class ArbitrarySignaturesMessage extends Message {
Serialization.serializeSizedString(bytes, this.peerAddress); Serialization.serializeSizedString(bytes, this.peerAddress);
bytes.write(Ints.toByteArray(this.requestHops));
bytes.write(Ints.toByteArray(this.signatures.size())); bytes.write(Ints.toByteArray(this.signatures.size()));
for (byte[] signature : this.signatures) for (byte[] signature : this.signatures)

View File

@ -214,8 +214,6 @@ public class Settings {
private int maxBlocksPerRequest = 100; private int maxBlocksPerRequest = 100;
/** Maximum number of blocks this node will serve in a single response */ /** Maximum number of blocks this node will serve in a single response */
private int maxBlocksPerResponse = 200; private int maxBlocksPerResponse = 200;
/** Maximum number of untrimmed blocks this node will serve in a single response */
private int maxUntrimmedBlocksPerResponse = 10;
// Which blockchains this node is running // Which blockchains this node is running
private String blockchainConfig = null; // use default from resources private String blockchainConfig = null; // use default from resources
@ -284,7 +282,7 @@ public class Settings {
private String tempDataPath = null; private String tempDataPath = null;
/** Storage policy to indicate which data should be hosted */ /** Storage policy to indicate which data should be hosted */
private String storagePolicy = "FOLLOWED_AND_VIEWED"; private String storagePolicy = "FOLLOWED_OR_VIEWED";
/** Whether to allow data outside of the storage policy to be relayed between other peers */ /** Whether to allow data outside of the storage policy to be relayed between other peers */
private boolean relayModeEnabled = true; private boolean relayModeEnabled = true;
@ -709,8 +707,6 @@ public class Settings {
public int getMaxBlocksPerResponse() { return this.maxBlocksPerResponse; } public int getMaxBlocksPerResponse() { return this.maxBlocksPerResponse; }
public int getMaxUntrimmedBlocksPerResponse() { return this.maxUntrimmedBlocksPerResponse; }
public boolean isAutoUpdateEnabled() { public boolean isAutoUpdateEnabled() {
return this.autoUpdateEnabled; return this.autoUpdateEnabled;
} }

View File

@ -228,7 +228,7 @@ public class ArbitraryTransaction extends Transaction {
if (ArbitraryDataStorageManager.getInstance().canStoreData(arbitraryTransactionData)) { if (ArbitraryDataStorageManager.getInstance().canStoreData(arbitraryTransactionData)) {
// Use a null peer address to indicate our own // Use a null peer address to indicate our own
byte[] signature = arbitraryTransactionData.getSignature(); byte[] signature = arbitraryTransactionData.getSignature();
Message arbitrarySignatureMessage = new ArbitrarySignaturesMessage(null, Arrays.asList(signature)); Message arbitrarySignatureMessage = new ArbitrarySignaturesMessage(null, 0, Arrays.asList(signature));
Network.getInstance().broadcast(broadcastPeer -> arbitrarySignatureMessage); Network.getInstance().broadcast(broadcastPeer -> arbitrarySignatureMessage);
} }
} }

View File

@ -68,7 +68,7 @@ public class ArbitraryDataStoragePolicyTests extends Common {
assertTrue(ResourceListManager.getInstance().addToList("followedNames", name, false)); assertTrue(ResourceListManager.getInstance().addToList("followedNames", name, false));
// We should store and pre-fetch data for this transaction // We should store and pre-fetch data for this transaction
assertEquals(StoragePolicy.FOLLOWED_AND_VIEWED, Settings.getInstance().getStoragePolicy()); assertEquals(StoragePolicy.FOLLOWED_OR_VIEWED, Settings.getInstance().getStoragePolicy());
assertTrue(storageManager.canStoreData(transactionData)); assertTrue(storageManager.canStoreData(transactionData));
assertTrue(storageManager.shouldPreFetchData(repository, transactionData)); assertTrue(storageManager.shouldPreFetchData(repository, transactionData));

View File

@ -14,7 +14,7 @@
"dataPath": "data-test", "dataPath": "data-test",
"tempDataPath": "data-test/_temp", "tempDataPath": "data-test/_temp",
"listsPath": "lists-test", "listsPath": "lists-test",
"storagePolicy": "FOLLOWED_AND_VIEWED", "storagePolicy": "FOLLOWED_OR_VIEWED",
"maxStorageCapacity": 104857600, "maxStorageCapacity": 104857600,
"localAuthBypassEnabled": true "localAuthBypassEnabled": true
} }