forked from Qortal/qortal
Allow identical data to be published if the metadata differs.
This commit is contained in:
parent
46606152eb
commit
cbd1018ecf
@ -6,6 +6,7 @@ import org.qortal.arbitrary.exception.MissingDataException;
|
|||||||
import org.qortal.arbitrary.ArbitraryDataFile.ResourceIdType;
|
import org.qortal.arbitrary.ArbitraryDataFile.ResourceIdType;
|
||||||
import org.qortal.arbitrary.ArbitraryDataDiff.*;
|
import org.qortal.arbitrary.ArbitraryDataDiff.*;
|
||||||
import org.qortal.arbitrary.metadata.ArbitraryDataMetadataPatch;
|
import org.qortal.arbitrary.metadata.ArbitraryDataMetadataPatch;
|
||||||
|
import org.qortal.arbitrary.metadata.ArbitraryDataTransactionMetadata;
|
||||||
import org.qortal.arbitrary.misc.Category;
|
import org.qortal.arbitrary.misc.Category;
|
||||||
import org.qortal.arbitrary.misc.Service;
|
import org.qortal.arbitrary.misc.Service;
|
||||||
import org.qortal.crypto.Crypto;
|
import org.qortal.crypto.Crypto;
|
||||||
@ -27,6 +28,7 @@ import java.io.IOException;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public class ArbitraryDataTransactionBuilder {
|
public class ArbitraryDataTransactionBuilder {
|
||||||
@ -79,9 +81,9 @@ public class ArbitraryDataTransactionBuilder {
|
|||||||
this.identifier = identifier;
|
this.identifier = identifier;
|
||||||
|
|
||||||
// Metadata (optional)
|
// Metadata (optional)
|
||||||
this.title = title;
|
this.title = ArbitraryDataTransactionMetadata.limitTitle(title);
|
||||||
this.description = description;
|
this.description = ArbitraryDataTransactionMetadata.limitDescription(description);
|
||||||
this.tags = tags;
|
this.tags = ArbitraryDataTransactionMetadata.limitTags(tags);
|
||||||
this.category = category;
|
this.category = category;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,6 +123,10 @@ public class ArbitraryDataTransactionBuilder {
|
|||||||
return Method.PUT;
|
return Method.PUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get existing metadata and see if it matches the new metadata
|
||||||
|
ArbitraryDataResource resource = new ArbitraryDataResource(this.name, ResourceIdType.NAME, this.service, this.identifier);
|
||||||
|
ArbitraryDataTransactionMetadata existingMetadata = resource.getLatestTransactionMetadata();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Check layer count
|
// Check layer count
|
||||||
int layerCount = reader.getLayerCount();
|
int layerCount = reader.getLayerCount();
|
||||||
@ -131,7 +137,23 @@ public class ArbitraryDataTransactionBuilder {
|
|||||||
|
|
||||||
// Check size of differences between this layer and previous layer
|
// Check size of differences between this layer and previous layer
|
||||||
ArbitraryDataCreatePatch patch = new ArbitraryDataCreatePatch(reader.getFilePath(), this.path, reader.getLatestSignature());
|
ArbitraryDataCreatePatch patch = new ArbitraryDataCreatePatch(reader.getFilePath(), this.path, reader.getLatestSignature());
|
||||||
patch.create();
|
try {
|
||||||
|
patch.create();
|
||||||
|
}
|
||||||
|
catch (DataException | IOException e) {
|
||||||
|
// Handle matching states separately, as it's best to block transactions with duplicate states
|
||||||
|
if (e.getMessage().equals("Current state matches previous state. Nothing to do.")) {
|
||||||
|
// Only throw an exception if the metadata is also identical, as well as the data
|
||||||
|
if (this.isMetadataEqual(existingMetadata)) {
|
||||||
|
throw new DataException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("Caught exception when creating patch: {}", e.getMessage());
|
||||||
|
LOGGER.info("Unable to load existing resource - using PUT to overwrite it.");
|
||||||
|
return Method.PUT;
|
||||||
|
}
|
||||||
|
|
||||||
long diffSize = FilesystemUtils.getDirectorySize(patch.getFinalPath());
|
long diffSize = FilesystemUtils.getDirectorySize(patch.getFinalPath());
|
||||||
long existingStateSize = FilesystemUtils.getDirectorySize(reader.getFilePath());
|
long existingStateSize = FilesystemUtils.getDirectorySize(reader.getFilePath());
|
||||||
double difference = (double) diffSize / (double) existingStateSize;
|
double difference = (double) diffSize / (double) existingStateSize;
|
||||||
@ -168,11 +190,8 @@ public class ArbitraryDataTransactionBuilder {
|
|||||||
// State is appropriate for a PATCH transaction
|
// State is appropriate for a PATCH transaction
|
||||||
return Method.PATCH;
|
return Method.PATCH;
|
||||||
}
|
}
|
||||||
catch (IOException | DataException e) {
|
catch (IOException e) {
|
||||||
// Handle matching states separately, as it's best to block transactions with duplicate states
|
// IMPORTANT: Don't catch DataException here, as they must be passed to the caller
|
||||||
if (e.getMessage().equals("Current state matches previous state. Nothing to do.")) {
|
|
||||||
throw new DataException(e.getMessage());
|
|
||||||
}
|
|
||||||
LOGGER.info("Caught exception: {}", e.getMessage());
|
LOGGER.info("Caught exception: {}", e.getMessage());
|
||||||
LOGGER.info("Unable to load existing resource - using PUT to overwrite it.");
|
LOGGER.info("Unable to load existing resource - using PUT to overwrite it.");
|
||||||
return Method.PUT;
|
return Method.PUT;
|
||||||
@ -267,6 +286,22 @@ public class ArbitraryDataTransactionBuilder {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isMetadataEqual(ArbitraryDataTransactionMetadata existingMetadata) {
|
||||||
|
if (!Objects.equals(existingMetadata.getTitle(), this.title)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(existingMetadata.getDescription(), this.description)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(existingMetadata.getCategory(), this.category)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(existingMetadata.getTags(), this.tags)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public void computeNonce() throws DataException {
|
public void computeNonce() throws DataException {
|
||||||
if (this.arbitraryTransactionData == null) {
|
if (this.arbitraryTransactionData == null) {
|
||||||
throw new DataException("Arbitrary transaction data is required to compute nonce");
|
throw new DataException("Arbitrary transaction data is required to compute nonce");
|
||||||
|
@ -172,6 +172,9 @@ public class ArbitraryDataTransactionMetadata extends ArbitraryDataMetadata {
|
|||||||
if (title == null) {
|
if (title == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (title.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return title.substring(0, Math.min(title.length(), MAX_TITLE_LENGTH));
|
return title.substring(0, Math.min(title.length(), MAX_TITLE_LENGTH));
|
||||||
}
|
}
|
||||||
@ -180,6 +183,9 @@ public class ArbitraryDataTransactionMetadata extends ArbitraryDataMetadata {
|
|||||||
if (description == null) {
|
if (description == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (description.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return description.substring(0, Math.min(description.length(), MAX_DESCRIPTION_LENGTH));
|
return description.substring(0, Math.min(description.length(), MAX_DESCRIPTION_LENGTH));
|
||||||
}
|
}
|
||||||
@ -199,10 +205,11 @@ public class ArbitraryDataTransactionMetadata extends ArbitraryDataMetadata {
|
|||||||
|
|
||||||
// Remove tags over the limit
|
// Remove tags over the limit
|
||||||
// This is cleaner than truncating, which results in malformed tags
|
// This is cleaner than truncating, which results in malformed tags
|
||||||
|
// Also remove tags that are empty
|
||||||
Iterator iterator = mutableTags.iterator();
|
Iterator iterator = mutableTags.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
String tag = (String) iterator.next();
|
String tag = (String) iterator.next();
|
||||||
if (tag == null || tag.length() > MAX_TAG_LENGTH) {
|
if (tag == null || tag.length() > MAX_TAG_LENGTH || tag.isEmpty()) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user