forked from Qortal/qortal
Modified storage code to support 2 new settings:
publicDataEnabled - whether to store decryptable data (default true) privateDataEnabled - whether to store data without a decryption key (default false)
This commit is contained in:
parent
f6b9ff50c3
commit
1b170c74c0
@ -372,6 +372,7 @@ public class ArbitraryDataReader {
|
|||||||
|
|
||||||
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | NoSuchPaddingException
|
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | NoSuchPaddingException
|
||||||
| BadPaddingException | IllegalBlockSizeException | IOException | InvalidKeyException e) {
|
| BadPaddingException | IllegalBlockSizeException | IOException | InvalidKeyException e) {
|
||||||
|
// TODO: delete files and blacklist this resource if privateDataEnabled is false
|
||||||
throw new DataException(String.format("Unable to decrypt file at path %s: %s", this.filePath, e.getMessage()));
|
throw new DataException(String.format("Unable to decrypt file at path %s: %s", this.filePath, e.getMessage()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -128,9 +128,9 @@ public class ArbitraryDataCleanupManager extends Thread {
|
|||||||
|
|
||||||
|
|
||||||
// Check to see if we should be hosting data for this transaction at all
|
// Check to see if we should be hosting data for this transaction at all
|
||||||
if (!storageManager.canStoreDataForName(arbitraryTransactionData.getName())) {
|
if (!storageManager.canStoreData(arbitraryTransactionData)) {
|
||||||
LOGGER.info("Deleting transaction {} because we can't host data for name {}",
|
LOGGER.info("Deleting transaction {} because we can't host its data",
|
||||||
Base58.encode(arbitraryTransactionData.getSignature()), arbitraryTransactionData.getName());
|
Base58.encode(arbitraryTransactionData.getSignature()));
|
||||||
ArbitraryTransactionUtils.deleteCompleteFileAndChunks(arbitraryTransactionData);
|
ArbitraryTransactionUtils.deleteCompleteFileAndChunks(arbitraryTransactionData);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -190,7 +190,7 @@ public class ArbitraryDataManager extends Thread {
|
|||||||
ArbitraryTransactionData arbitraryTransactionData = (ArbitraryTransactionData) arbitraryTransaction.getTransactionData();
|
ArbitraryTransactionData arbitraryTransactionData = (ArbitraryTransactionData) arbitraryTransaction.getTransactionData();
|
||||||
|
|
||||||
// Skip transactions that we don't need to proactively store data for
|
// Skip transactions that we don't need to proactively store data for
|
||||||
if (!storageManager.shouldPreFetchDataForName(arbitraryTransactionData.getName())) {
|
if (!storageManager.shouldPreFetchData(arbitraryTransactionData)) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -680,7 +680,7 @@ public class ArbitraryDataManager extends Thread {
|
|||||||
|
|
||||||
// We may also need to broadcast to the network that we are now hosting files for this transaction,
|
// We may also need to broadcast to the network that we are now hosting files for this transaction,
|
||||||
// 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().canStoreDataForName(arbitraryTransactionData.getName())) {
|
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, Arrays.asList(signature));
|
||||||
Network.getInstance().broadcast(broadcastPeer -> newArbitrarySignatureMessage);
|
Network.getInstance().broadcast(broadcastPeer -> newArbitrarySignatureMessage);
|
||||||
@ -863,7 +863,7 @@ public class ArbitraryDataManager extends Thread {
|
|||||||
if (transactionData instanceof ArbitraryTransactionData) {
|
if (transactionData instanceof ArbitraryTransactionData) {
|
||||||
|
|
||||||
// Check if we're even allowed to serve data for this transaction
|
// Check if we're even allowed to serve data for this transaction
|
||||||
if (ArbitraryDataStorageManager.getInstance().canStoreDataForName(transactionData.getName())) {
|
if (ArbitraryDataStorageManager.getInstance().canStoreData(transactionData)) {
|
||||||
|
|
||||||
byte[] hash = transactionData.getData();
|
byte[] hash = transactionData.getData();
|
||||||
byte[] chunkHashes = transactionData.getChunkHashes();
|
byte[] chunkHashes = transactionData.getChunkHashes();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.qortal.controller.arbitrary;
|
package org.qortal.controller.arbitrary;
|
||||||
|
|
||||||
|
import org.qortal.data.transaction.ArbitraryTransactionData;
|
||||||
import org.qortal.list.ResourceListManager;
|
import org.qortal.list.ResourceListManager;
|
||||||
import org.qortal.settings.Settings;
|
import org.qortal.settings.Settings;
|
||||||
|
|
||||||
@ -25,7 +26,14 @@ public class ArbitraryDataStorageManager {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canStoreDataForName(String name) {
|
public boolean canStoreData(ArbitraryTransactionData arbitraryTransactionData) {
|
||||||
|
String name = arbitraryTransactionData.getName();
|
||||||
|
|
||||||
|
// Don't store data unless it's an allowed type (public/private)
|
||||||
|
if (!this.isDataTypeAllowed(arbitraryTransactionData)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if our storage policy and blacklist allows us to host data for this name
|
// Check if our storage policy and blacklist allows us to host data for this name
|
||||||
switch (Settings.getInstance().getStoragePolicy()) {
|
switch (Settings.getInstance().getStoragePolicy()) {
|
||||||
case FOLLOWED_AND_VIEWED:
|
case FOLLOWED_AND_VIEWED:
|
||||||
@ -45,18 +53,19 @@ public class ArbitraryDataStorageManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNameInBlacklist(String name) {
|
public boolean shouldPreFetchData(ArbitraryTransactionData arbitraryTransactionData) {
|
||||||
return ResourceListManager.getInstance().listContains("blacklist", "names", name, false);
|
String name = arbitraryTransactionData.getName();
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shouldPreFetchDataForName(String name) {
|
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
return this.shouldPreFetchDataWithoutName();
|
return this.shouldPreFetchDataWithoutName(arbitraryTransactionData);
|
||||||
}
|
}
|
||||||
// Never fetch data from blacklisted names, even if they are followed
|
// Never fetch data from blacklisted names, even if they are followed
|
||||||
if (this.isNameInBlacklist(name)) {
|
if (this.isNameInBlacklist(name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// Don't store data unless it's an allowed type (public/private)
|
||||||
|
if (!this.isDataTypeAllowed(arbitraryTransactionData)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
switch (Settings.getInstance().getStoragePolicy()) {
|
switch (Settings.getInstance().getStoragePolicy()) {
|
||||||
case FOLLOWED:
|
case FOLLOWED:
|
||||||
@ -73,10 +82,10 @@ public class ArbitraryDataStorageManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldPreFetchDataWithoutName() {
|
private boolean shouldPreFetchDataWithoutName(ArbitraryTransactionData arbitraryTransactionData) {
|
||||||
switch (Settings.getInstance().getStoragePolicy()) {
|
switch (Settings.getInstance().getStoragePolicy()) {
|
||||||
case ALL:
|
case ALL:
|
||||||
return true;
|
return this.isDataTypeAllowed(arbitraryTransactionData);
|
||||||
|
|
||||||
case NONE:
|
case NONE:
|
||||||
case VIEWED:
|
case VIEWED:
|
||||||
@ -87,6 +96,25 @@ public class ArbitraryDataStorageManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isDataTypeAllowed(ArbitraryTransactionData arbitraryTransactionData) {
|
||||||
|
byte[] secret = arbitraryTransactionData.getSecret();
|
||||||
|
boolean hasSecret = (secret != null && secret.length == 32);
|
||||||
|
|
||||||
|
if (!Settings.getInstance().isPrivateDataEnabled() && !hasSecret) {
|
||||||
|
// Private data isn't enabled so we can't store data without a valid secret
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Settings.getInstance().isPublicDataEnabled() && hasSecret) {
|
||||||
|
// Public data isn't enabled so we can't store data with a secret
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNameInBlacklist(String name) {
|
||||||
|
return ResourceListManager.getInstance().listContains("blacklist", "names", name, false);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isFollowingName(String name) {
|
private boolean isFollowingName(String name) {
|
||||||
return ResourceListManager.getInstance().listContains("followed", "names", name, false);
|
return ResourceListManager.getInstance().listContains("followed", "names", name, false);
|
||||||
}
|
}
|
||||||
|
@ -284,6 +284,11 @@ public class Settings {
|
|||||||
/** Whether to validate every layer when building arbitrary data, or just the final layer */
|
/** Whether to validate every layer when building arbitrary data, or just the final layer */
|
||||||
private boolean validateAllDataLayers = false;
|
private boolean validateAllDataLayers = false;
|
||||||
|
|
||||||
|
/** Whether to allow public (decryptable) data to be stored */
|
||||||
|
private boolean publicDataEnabled = true;
|
||||||
|
/** Whether to allow private (non-decryptable) data to be stored */
|
||||||
|
private boolean privateDataEnabled = false;
|
||||||
|
|
||||||
|
|
||||||
// Domain mapping
|
// Domain mapping
|
||||||
public static class DomainMap {
|
public static class DomainMap {
|
||||||
@ -827,4 +832,12 @@ public class Settings {
|
|||||||
public boolean shouldValidateAllDataLayers() {
|
public boolean shouldValidateAllDataLayers() {
|
||||||
return this.validateAllDataLayers;
|
return this.validateAllDataLayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPublicDataEnabled() {
|
||||||
|
return this.publicDataEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPrivateDataEnabled() {
|
||||||
|
return this.privateDataEnabled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
package org.qortal.test.arbitrary;public class ArbitraryDataStoragePolicyTests {
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user