diff --git a/src/main/java/org/qortal/api/resource/ArbitraryResource.java b/src/main/java/org/qortal/api/resource/ArbitraryResource.java index a5a97123..78cf9213 100644 --- a/src/main/java/org/qortal/api/resource/ArbitraryResource.java +++ b/src/main/java/org/qortal/api/resource/ArbitraryResource.java @@ -45,8 +45,8 @@ import org.qortal.repository.DataException; import org.qortal.repository.Repository; import org.qortal.repository.RepositoryManager; import org.qortal.settings.Settings; -import org.qortal.storage.DataFile; -import org.qortal.storage.DataFileChunk; +import org.qortal.storage.ArbitraryDataFile; +import org.qortal.storage.ArbitraryDataFileChunk; import org.qortal.storage.ArbitraryDataWriter; import org.qortal.transaction.ArbitraryTransaction; import org.qortal.transaction.Transaction; @@ -281,28 +281,28 @@ public class ArbitraryResource { throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA); } - DataFile dataFile = arbitraryDataWriter.getDataFile(); - if (dataFile == null) { + ArbitraryDataFile arbitraryDataFile = arbitraryDataWriter.getArbitraryDataFile(); + if (arbitraryDataFile == null) { throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA); } try (final Repository repository = RepositoryManager.getRepository()) { - DataFile.ValidationResult validationResult = dataFile.isValid(); - if (validationResult != DataFile.ValidationResult.OK) { + ArbitraryDataFile.ValidationResult validationResult = arbitraryDataFile.isValid(); + if (validationResult != ArbitraryDataFile.ValidationResult.OK) { LOGGER.error("Invalid file: {}", validationResult); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA); } - LOGGER.info("Whole file digest: {}", dataFile.digest58()); + LOGGER.info("Whole file digest: {}", arbitraryDataFile.digest58()); - int chunkCount = dataFile.split(DataFile.CHUNK_SIZE); + int chunkCount = arbitraryDataFile.split(ArbitraryDataFile.CHUNK_SIZE); if (chunkCount == 0) { LOGGER.error("No chunks created"); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA); } LOGGER.info(String.format("Successfully split into %d chunk%s", chunkCount, (chunkCount == 1 ? "" : "s"))); - String digest58 = dataFile.digest58(); + String digest58 = arbitraryDataFile.digest58(); if (digest58 == null) { LOGGER.error("Unable to calculate digest"); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA); @@ -313,12 +313,12 @@ public class ArbitraryResource { final BaseTransactionData baseTransactionData = new BaseTransactionData(NTP.getTime(), Group.NO_GROUP, lastReference, creatorPublicKey, BlockChain.getInstance().getUnitFee(), null); - final int size = (int)dataFile.size(); + final int size = (int) arbitraryDataFile.size(); final int version = 5; final int nonce = 0; final ArbitraryTransactionData.DataType dataType = ArbitraryTransactionData.DataType.DATA_HASH; - final byte[] digest = dataFile.digest(); - final byte[] chunkHashes = dataFile.chunkHashes(); + final byte[] digest = arbitraryDataFile.digest(); + final byte[] chunkHashes = arbitraryDataFile.chunkHashes(); final List payments = new ArrayList<>(); ArbitraryTransactionData transactionData = new ArbitraryTransactionData(baseTransactionData, @@ -330,7 +330,7 @@ public class ArbitraryResource { Transaction.ValidationResult result = transaction.isValidUnconfirmed(); if (result != Transaction.ValidationResult.OK) { - dataFile.deleteAll(); + arbitraryDataFile.deleteAll(); throw TransactionsResource.createTransactionInvalidException(request, result); } @@ -338,14 +338,14 @@ public class ArbitraryResource { return Base58.encode(bytes); } catch (DataException e) { - dataFile.deleteAll(); + arbitraryDataFile.deleteAll(); LOGGER.error("Repository issue when uploading data", e); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); } catch (TransformationException e) { - dataFile.deleteAll(); + arbitraryDataFile.deleteAll(); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e); } catch (IllegalStateException e) { - dataFile.deleteAll(); + arbitraryDataFile.deleteAll(); LOGGER.error("Invalid upload data", e); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA, e); } @@ -380,8 +380,8 @@ public class ArbitraryResource { public String deleteFile(String hash58) { Security.checkApiCallAllowed(request); - DataFile dataFile = DataFile.fromHash58(hash58); - if (dataFile.delete()) { + ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash58(hash58); + if (arbitraryDataFile.delete()) { return "true"; } return "false"; @@ -503,9 +503,9 @@ public class ArbitraryResource { private boolean requestFile(String hash58, Peer targetPeer) { try (final Repository repository = RepositoryManager.getRepository()) { - DataFile dataFile = DataFile.fromHash58(hash58); - if (dataFile.exists()) { - LOGGER.info("Data file {} already exists but we'll request it anyway", dataFile); + ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash58(hash58); + if (arbitraryDataFile.exists()) { + LOGGER.info("Data file {} already exists but we'll request it anyway", arbitraryDataFile); } byte[] digest = null; @@ -526,11 +526,11 @@ public class ArbitraryResource { } DataFileMessage dataFileMessage = (DataFileMessage) message; - dataFile = dataFileMessage.getDataFile(); - if (dataFile == null || !dataFile.exists()) { + arbitraryDataFile = dataFileMessage.getArbitraryDataFile(); + if (arbitraryDataFile == null || !arbitraryDataFile.exists()) { return false; } - LOGGER.info(String.format("Received file %s, size %d bytes", dataFileMessage.getDataFile(), dataFileMessage.getDataFile().size())); + LOGGER.info(String.format("Received file %s, size %d bytes", dataFileMessage.getArbitraryDataFile(), dataFileMessage.getArbitraryDataFile().size())); return true; } catch (ApiException e) { throw e; @@ -571,22 +571,22 @@ public class ArbitraryResource { throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); } - DataFile dataFile = DataFile.fromHash58(combinedHash); - if (dataFile.exists()) { + ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash58(combinedHash); + if (arbitraryDataFile.exists()) { LOGGER.info("We already have the combined file {}, but we'll join the chunks anyway.", combinedHash); } String hash58List[] = files.split(","); for (String hash58 : hash58List) { if (hash58 != null) { - DataFileChunk chunk = DataFileChunk.fromHash58(hash58); - dataFile.addChunk(chunk); + ArbitraryDataFileChunk chunk = ArbitraryDataFileChunk.fromHash58(hash58); + arbitraryDataFile.addChunk(chunk); } } - boolean success = dataFile.join(); + boolean success = arbitraryDataFile.join(); if (success) { - if (combinedHash.equals(dataFile.digest58())) { - LOGGER.info("Valid hash {} after joining {} files", dataFile.digest58(), dataFile.chunkCount()); + if (combinedHash.equals(arbitraryDataFile.digest58())) { + LOGGER.info("Valid hash {} after joining {} files", arbitraryDataFile.digest58(), arbitraryDataFile.chunkCount()); return Response.ok("true").build(); } } diff --git a/src/main/java/org/qortal/api/resource/WebsiteResource.java b/src/main/java/org/qortal/api/resource/WebsiteResource.java index 85fbd087..933452a0 100644 --- a/src/main/java/org/qortal/api/resource/WebsiteResource.java +++ b/src/main/java/org/qortal/api/resource/WebsiteResource.java @@ -38,8 +38,8 @@ import org.qortal.repository.DataException; import org.qortal.repository.Repository; import org.qortal.repository.RepositoryManager; import org.qortal.settings.Settings; -import org.qortal.storage.DataFile; -import org.qortal.storage.DataFile.*; +import org.qortal.storage.ArbitraryDataFile; +import org.qortal.storage.ArbitraryDataFile.*; import org.qortal.storage.ArbitraryDataReader; import org.qortal.storage.ArbitraryDataWriter; import org.qortal.transaction.ArbitraryTransaction; @@ -112,12 +112,12 @@ public class WebsiteResource { throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA); } - DataFile dataFile = arbitraryDataWriter.getDataFile(); - if (dataFile == null) { + ArbitraryDataFile arbitraryDataFile = arbitraryDataWriter.getArbitraryDataFile(); + if (arbitraryDataFile == null) { throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA); } - String digest58 = dataFile.digest58(); + String digest58 = arbitraryDataFile.digest58(); if (digest58 == null) { LOGGER.error("Unable to calculate digest"); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA); @@ -130,13 +130,13 @@ public class WebsiteResource { final BaseTransactionData baseTransactionData = new BaseTransactionData(NTP.getTime(), Group.NO_GROUP, lastReference, creatorPublicKey, BlockChain.getInstance().getUnitFee(), null); - final int size = (int)dataFile.size(); + final int size = (int) arbitraryDataFile.size(); final int version = 5; final int nonce = 0; - byte[] secret = dataFile.getSecret(); + byte[] secret = arbitraryDataFile.getSecret(); final ArbitraryTransactionData.DataType dataType = ArbitraryTransactionData.DataType.DATA_HASH; - final byte[] digest = dataFile.digest(); - final byte[] chunkHashes = dataFile.chunkHashes(); + final byte[] digest = arbitraryDataFile.digest(); + final byte[] chunkHashes = arbitraryDataFile.chunkHashes(); final List payments = new ArrayList<>(); ArbitraryTransactionData transactionData = new ArbitraryTransactionData(baseTransactionData, @@ -149,7 +149,7 @@ public class WebsiteResource { Transaction.ValidationResult result = transaction.isValidUnconfirmed(); if (result != Transaction.ValidationResult.OK) { - dataFile.deleteAll(); + arbitraryDataFile.deleteAll(); throw TransactionsResource.createTransactionInvalidException(request, result); } @@ -157,10 +157,10 @@ public class WebsiteResource { return Base58.encode(bytes); } catch (TransformationException e) { - dataFile.deleteAll(); + arbitraryDataFile.deleteAll(); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e); } catch (DataException e) { - dataFile.deleteAll(); + arbitraryDataFile.deleteAll(); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); } } @@ -212,11 +212,11 @@ public class WebsiteResource { throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA); } - DataFile dataFile = arbitraryDataWriter.getDataFile(); - if (dataFile != null) { - String digest58 = dataFile.digest58(); + ArbitraryDataFile arbitraryDataFile = arbitraryDataWriter.getArbitraryDataFile(); + if (arbitraryDataFile != null) { + String digest58 = arbitraryDataFile.digest58(); if (digest58 != null) { - return "http://localhost:12393/site/hash/" + digest58 + "?secret=" + Base58.encode(dataFile.getSecret()); + return "http://localhost:12393/site/hash/" + digest58 + "?secret=" + Base58.encode(arbitraryDataFile.getSecret()); } } return "Unable to generate preview URL"; diff --git a/src/main/java/org/qortal/controller/ArbitraryDataManager.java b/src/main/java/org/qortal/controller/ArbitraryDataManager.java index 29827e30..7028b550 100644 --- a/src/main/java/org/qortal/controller/ArbitraryDataManager.java +++ b/src/main/java/org/qortal/controller/ArbitraryDataManager.java @@ -13,8 +13,8 @@ import org.qortal.network.message.*; import org.qortal.repository.DataException; import org.qortal.repository.Repository; import org.qortal.repository.RepositoryManager; -import org.qortal.storage.DataFile; -import org.qortal.storage.DataFileChunk; +import org.qortal.storage.ArbitraryDataFile; +import org.qortal.storage.ArbitraryDataFileChunk; import org.qortal.transaction.ArbitraryTransaction; import org.qortal.transaction.Transaction.TransactionType; import org.qortal.utils.Base58; @@ -166,7 +166,7 @@ public class ArbitraryDataManager extends Thread { return true; } - private DataFile fetchArbitraryDataFile(Peer peer, byte[] hash) throws InterruptedException { + private ArbitraryDataFile fetchArbitraryDataFile(Peer peer, byte[] hash) throws InterruptedException { String hash58 = Base58.encode(hash); LOGGER.info(String.format("Fetching data file %.8s from peer %s", hash58, peer)); arbitraryDataFileRequests.put(hash58, NTP.getTime()); @@ -181,7 +181,7 @@ public class ArbitraryDataManager extends Thread { } DataFileMessage dataFileMessage = (DataFileMessage) message; - return dataFileMessage.getDataFile(); + return dataFileMessage.getArbitraryDataFile(); } public void cleanupRequestCache(long now) { @@ -269,13 +269,13 @@ public class ArbitraryDataManager extends Thread { ArbitraryTransactionData arbitraryTransactionData = (ArbitraryTransactionData) transactionData; // Load data file(s) - DataFile dataFile = DataFile.fromHash(arbitraryTransactionData.getData()); - dataFile.addChunkHashes(arbitraryTransactionData.getChunkHashes()); + ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash(arbitraryTransactionData.getData()); + arbitraryDataFile.addChunkHashes(arbitraryTransactionData.getChunkHashes()); // Check all hashes exist for (byte[] hash : hashes) { //LOGGER.info("Received hash {}", Base58.encode(hash)); - if (!dataFile.containsChunk(hash)) { + if (!arbitraryDataFile.containsChunk(hash)) { LOGGER.info("Received non-matching chunk hash {} for signature {}", Base58.encode(hash), signature58); return; } @@ -287,14 +287,14 @@ public class ArbitraryDataManager extends Thread { // Now fetch actual data from this peer for (byte[] hash : hashes) { - if (!dataFile.chunkExists(hash)) { + if (!arbitraryDataFile.chunkExists(hash)) { // Only request the file if we aren't already requesting it from someone else if (!arbitraryDataFileRequests.containsKey(Base58.encode(hash))) { - DataFile receivedDataFile = fetchArbitraryDataFile(peer, hash); - LOGGER.info("Received data file {} from peer {}", receivedDataFile, peer); + ArbitraryDataFile receivedArbitraryDataFile = fetchArbitraryDataFile(peer, hash); + LOGGER.info("Received data file {} from peer {}", receivedArbitraryDataFile, peer); } else { - LOGGER.info("Already requesting data file {}", dataFile); + LOGGER.info("Already requesting data file {}", arbitraryDataFile); } } } @@ -318,15 +318,15 @@ public class ArbitraryDataManager extends Thread { byte[] hash = getDataFileMessage.getHash(); Controller.getInstance().stats.getDataFileMessageStats.requests.incrementAndGet(); - DataFile dataFile = DataFile.fromHash(hash); - if (dataFile.exists()) { - DataFileMessage dataFileMessage = new DataFileMessage(dataFile); + ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash(hash); + if (arbitraryDataFile.exists()) { + DataFileMessage dataFileMessage = new DataFileMessage(arbitraryDataFile); dataFileMessage.setId(message.getId()); if (!peer.sendMessage(dataFileMessage)) { LOGGER.info("Couldn't sent file"); peer.disconnect("failed to send file"); } - LOGGER.info("Sent file {}", dataFile); + LOGGER.info("Sent file {}", arbitraryDataFile); } else { @@ -334,7 +334,7 @@ public class ArbitraryDataManager extends Thread { Controller.getInstance().stats.getDataFileMessageStats.unknownFiles.getAndIncrement(); // Send valid, yet unexpected message type in response, so peer's synchronizer doesn't have to wait for timeout - LOGGER.debug(() -> String.format("Sending 'file unknown' response to peer %s for GET_FILE request for unknown file %s", peer, dataFile)); + LOGGER.debug(() -> String.format("Sending 'file unknown' response to peer %s for GET_FILE request for unknown file %s", peer, arbitraryDataFile)); // We'll send empty block summaries message as it's very short // TODO: use a different message type here @@ -344,7 +344,7 @@ public class ArbitraryDataManager extends Thread { LOGGER.info("Couldn't sent file-unknown response"); peer.disconnect("failed to send file-unknown response"); } - LOGGER.info("Sent file-unknown response for file {}", dataFile); + LOGGER.info("Sent file-unknown response for file {}", arbitraryDataFile); } } @@ -367,10 +367,10 @@ public class ArbitraryDataManager extends Thread { byte[] chunkHashes = transactionData.getChunkHashes(); // Load file(s) and add any that exist to the list of hashes - DataFile dataFile = DataFile.fromHash(hash); + ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash(hash); if (chunkHashes != null && chunkHashes.length > 0) { - dataFile.addChunkHashes(chunkHashes); - for (DataFileChunk dataFileChunk : dataFile.getChunks()) { + arbitraryDataFile.addChunkHashes(chunkHashes); + for (ArbitraryDataFileChunk dataFileChunk : arbitraryDataFile.getChunks()) { if (dataFileChunk.exists()) { hashes.add(dataFileChunk.getHash()); //LOGGER.info("Added hash {}", dataFileChunk.getHash58()); diff --git a/src/main/java/org/qortal/network/message/DataFileMessage.java b/src/main/java/org/qortal/network/message/DataFileMessage.java index e31dde67..a2a144dd 100644 --- a/src/main/java/org/qortal/network/message/DataFileMessage.java +++ b/src/main/java/org/qortal/network/message/DataFileMessage.java @@ -1,7 +1,7 @@ package org.qortal.network.message; import com.google.common.primitives.Ints; -import org.qortal.storage.DataFile; +import org.qortal.storage.ArbitraryDataFile; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -10,22 +10,22 @@ import java.nio.ByteBuffer; public class DataFileMessage extends Message { - private final DataFile dataFile; + private final ArbitraryDataFile arbitraryDataFile; - public DataFileMessage(DataFile dataFile) { + public DataFileMessage(ArbitraryDataFile arbitraryDataFile) { super(MessageType.DATA_FILE); - this.dataFile = dataFile; + this.arbitraryDataFile = arbitraryDataFile; } - public DataFileMessage(int id, DataFile dataFile) { + public DataFileMessage(int id, ArbitraryDataFile arbitraryDataFile) { super(id, MessageType.DATA_FILE); - this.dataFile = dataFile; + this.arbitraryDataFile = arbitraryDataFile; } - public DataFile getDataFile() { - return this.dataFile; + public ArbitraryDataFile getArbitraryDataFile() { + return this.arbitraryDataFile; } public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws UnsupportedEncodingException { @@ -36,18 +36,18 @@ public class DataFileMessage extends Message { byte[] data = new byte[dataLength]; byteBuffer.get(data); - DataFile dataFile = new DataFile(data); + ArbitraryDataFile arbitraryDataFile = new ArbitraryDataFile(data); - return new DataFileMessage(id, dataFile); + return new DataFileMessage(id, arbitraryDataFile); } @Override protected byte[] toData() { - if (this.dataFile == null) { + if (this.arbitraryDataFile == null) { return null; } - byte[] data = this.dataFile.getBytes(); + byte[] data = this.arbitraryDataFile.getBytes(); if (data == null) { return null; } @@ -66,7 +66,7 @@ public class DataFileMessage extends Message { } public DataFileMessage cloneWithNewId(int newId) { - DataFileMessage clone = new DataFileMessage(this.dataFile); + DataFileMessage clone = new DataFileMessage(this.arbitraryDataFile); clone.setId(newId); return clone; } diff --git a/src/main/java/org/qortal/repository/hsqldb/HSQLDBArbitraryRepository.java b/src/main/java/org/qortal/repository/hsqldb/HSQLDBArbitraryRepository.java index 5bc174e2..dc70496f 100644 --- a/src/main/java/org/qortal/repository/hsqldb/HSQLDBArbitraryRepository.java +++ b/src/main/java/org/qortal/repository/hsqldb/HSQLDBArbitraryRepository.java @@ -10,7 +10,7 @@ import org.qortal.data.transaction.BaseTransactionData; import org.qortal.data.transaction.TransactionData; import org.qortal.repository.ArbitraryRepository; import org.qortal.repository.DataException; -import org.qortal.storage.DataFile; +import org.qortal.storage.ArbitraryDataFile; import org.qortal.transaction.Transaction.ApprovalStatus; import java.sql.ResultSet; @@ -55,18 +55,18 @@ public class HSQLDBArbitraryRepository implements ArbitraryRepository { byte[] chunkHashes = transactionData.getChunkHashes(); // Load data file(s) - DataFile dataFile = DataFile.fromHash(digest); + ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash(digest); if (chunkHashes != null && chunkHashes.length > 0) { - dataFile.addChunkHashes(chunkHashes); + arbitraryDataFile.addChunkHashes(chunkHashes); } // Check if we already have the complete data file - if (dataFile.exists()) { + if (arbitraryDataFile.exists()) { return true; } // Alternatively, if we have all the chunks, then it's safe to assume the data is local - if (dataFile.allChunksExist(chunkHashes)) { + if (arbitraryDataFile.allChunksExist(chunkHashes)) { return true; } @@ -90,23 +90,23 @@ public class HSQLDBArbitraryRepository implements ArbitraryRepository { byte[] chunkHashes = transactionData.getChunkHashes(); // Load data file(s) - DataFile dataFile = DataFile.fromHash(digest); + ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash(digest); if (chunkHashes != null && chunkHashes.length > 0) { - dataFile.addChunkHashes(chunkHashes); + arbitraryDataFile.addChunkHashes(chunkHashes); } // If we have the complete data file, return it - if (dataFile.exists()) { - return dataFile.getBytes(); + if (arbitraryDataFile.exists()) { + return arbitraryDataFile.getBytes(); } // Alternatively, if we have all the chunks, combine them into a single file - if (dataFile.allChunksExist(chunkHashes)) { - dataFile.join(); + if (arbitraryDataFile.allChunksExist(chunkHashes)) { + arbitraryDataFile.join(); // Verify that the combined hash matches the expected hash - if (digest.equals(dataFile.digest())) { - return dataFile.getBytes(); + if (digest.equals(arbitraryDataFile.digest())) { + return arbitraryDataFile.getBytes(); } } @@ -134,29 +134,29 @@ public class HSQLDBArbitraryRepository implements ArbitraryRepository { arbitraryTransactionData.setDataType(DataType.DATA_HASH); // Create DataFile - DataFile dataFile = new DataFile(rawData); + ArbitraryDataFile arbitraryDataFile = new ArbitraryDataFile(rawData); // Verify that the data file is valid, and that it matches the expected hash - DataFile.ValidationResult validationResult = dataFile.isValid(); - if (validationResult != DataFile.ValidationResult.OK) { - dataFile.deleteAll(); + ArbitraryDataFile.ValidationResult validationResult = arbitraryDataFile.isValid(); + if (validationResult != ArbitraryDataFile.ValidationResult.OK) { + arbitraryDataFile.deleteAll(); throw new DataException("Invalid data file when attempting to store arbitrary transaction data"); } - if (!dataHash.equals(dataFile.digest())) { - dataFile.deleteAll(); + if (!dataHash.equals(arbitraryDataFile.digest())) { + arbitraryDataFile.deleteAll(); throw new DataException("Could not verify hash when attempting to store arbitrary transaction data"); } // Now create chunks if needed - int chunkCount = dataFile.split(DataFile.CHUNK_SIZE); + int chunkCount = arbitraryDataFile.split(ArbitraryDataFile.CHUNK_SIZE); if (chunkCount > 0) { LOGGER.info(String.format("Successfully split into %d chunk%s:", chunkCount, (chunkCount == 1 ? "" : "s"))); - LOGGER.info("{}", dataFile.printChunks()); + LOGGER.info("{}", arbitraryDataFile.printChunks()); // Verify that the chunk hashes match those in the transaction - byte[] chunkHashes = dataFile.chunkHashes(); + byte[] chunkHashes = arbitraryDataFile.chunkHashes(); if (!chunkHashes.equals(arbitraryTransactionData.getChunkHashes())) { - dataFile.deleteAll(); + arbitraryDataFile.deleteAll(); throw new DataException("Could not verify chunk hashes when attempting to store arbitrary transaction data"); } @@ -175,13 +175,13 @@ public class HSQLDBArbitraryRepository implements ArbitraryRepository { byte[] chunkHashes = arbitraryTransactionData.getChunkHashes(); // Load data file(s) - DataFile dataFile = DataFile.fromHash(digest); + ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash(digest); if (chunkHashes != null && chunkHashes.length > 0) { - dataFile.addChunkHashes(chunkHashes); + arbitraryDataFile.addChunkHashes(chunkHashes); } // Delete file and chunks - dataFile.deleteAll(); + arbitraryDataFile.deleteAll(); } @Override diff --git a/src/main/java/org/qortal/storage/ArbitraryDataBuilder.java b/src/main/java/org/qortal/storage/ArbitraryDataBuilder.java index a04c5689..5da39e51 100644 --- a/src/main/java/org/qortal/storage/ArbitraryDataBuilder.java +++ b/src/main/java/org/qortal/storage/ArbitraryDataBuilder.java @@ -8,7 +8,7 @@ import org.qortal.data.transaction.ArbitraryTransactionData.Service; import org.qortal.repository.DataException; import org.qortal.repository.Repository; import org.qortal.repository.RepositoryManager; -import org.qortal.storage.DataFile.ResourceIdType; +import org.qortal.storage.ArbitraryDataFile.ResourceIdType; import org.qortal.utils.Base58; import java.io.IOException; diff --git a/src/main/java/org/qortal/storage/DataFile.java b/src/main/java/org/qortal/storage/ArbitraryDataFile.java similarity index 87% rename from src/main/java/org/qortal/storage/DataFile.java rename to src/main/java/org/qortal/storage/ArbitraryDataFile.java index 75579e1a..008a44d3 100644 --- a/src/main/java/org/qortal/storage/DataFile.java +++ b/src/main/java/org/qortal/storage/ArbitraryDataFile.java @@ -20,7 +20,7 @@ import static java.util.Arrays.stream; import static java.util.stream.Collectors.toMap; -public class DataFile { +public class ArbitraryDataFile { // Validation results public enum ValidationResult { @@ -30,13 +30,13 @@ public class DataFile { public final int value; - private static final Map map = stream(DataFile.ValidationResult.values()).collect(toMap(result -> result.value, result -> result)); + private static final Map map = stream(ArbitraryDataFile.ValidationResult.values()).collect(toMap(result -> result.value, result -> result)); ValidationResult(int value) { this.value = value; } - public static DataFile.ValidationResult valueOf(int value) { + public static ArbitraryDataFile.ValidationResult valueOf(int value) { return map.get(value); } } @@ -49,7 +49,7 @@ public class DataFile { NAME }; - private static final Logger LOGGER = LogManager.getLogger(DataFile.class); + private static final Logger LOGGER = LogManager.getLogger(ArbitraryDataFile.class); public static final long MAX_FILE_SIZE = 500 * 1024 * 1024; // 500MiB public static final int CHUNK_SIZE = 1 * 1024 * 1024; // 1MiB @@ -57,20 +57,20 @@ public class DataFile { protected String filePath; protected String hash58; - private ArrayList chunks; + private ArrayList chunks; private byte[] secret; - public DataFile() { + public ArbitraryDataFile() { } - public DataFile(String hash58) { + public ArbitraryDataFile(String hash58) { this.createDataDirectory(); - this.filePath = DataFile.getOutputFilePath(hash58, false); + this.filePath = ArbitraryDataFile.getOutputFilePath(hash58, false); this.chunks = new ArrayList<>(); this.hash58 = hash58; } - public DataFile(byte[] fileContent) { + public ArbitraryDataFile(byte[] fileContent) { if (fileContent == null) { LOGGER.error("fileContent is null"); return; @@ -95,28 +95,28 @@ public class DataFile { } } - public static DataFile fromHash58(String hash58) { - return new DataFile(hash58); + public static ArbitraryDataFile fromHash58(String hash58) { + return new ArbitraryDataFile(hash58); } - public static DataFile fromHash(byte[] hash) { - return DataFile.fromHash58(Base58.encode(hash)); + public static ArbitraryDataFile fromHash(byte[] hash) { + return ArbitraryDataFile.fromHash58(Base58.encode(hash)); } - public static DataFile fromPath(String path) { + public static ArbitraryDataFile fromPath(String path) { File file = new File(path); if (file.exists()) { try { byte[] fileContent = Files.readAllBytes(file.toPath()); byte[] digest = Crypto.digest(fileContent); - DataFile dataFile = DataFile.fromHash(digest); + ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash(digest); // Copy file to base directory if needed Path filePath = Paths.get(path); - if (Files.exists(filePath) && !dataFile.isInBaseDirectory(path)) { - dataFile.copyToDataDirectory(filePath); + if (Files.exists(filePath) && !arbitraryDataFile.isInBaseDirectory(path)) { + arbitraryDataFile.copyToDataDirectory(filePath); } - return dataFile; + return arbitraryDataFile; } catch (IOException e) { LOGGER.error("Couldn't compute digest for DataFile"); @@ -125,8 +125,8 @@ public class DataFile { return null; } - public static DataFile fromFile(File file) { - return DataFile.fromPath(file.getPath()); + public static ArbitraryDataFile fromFile(File file) { + return ArbitraryDataFile.fromPath(file.getPath()); } private boolean createDataDirectory() { @@ -188,7 +188,7 @@ public class DataFile { long fileSize = Files.size(path); if (fileSize > MAX_FILE_SIZE) { LOGGER.error(String.format("DataFile is too large: %d bytes (max size: %d bytes)", fileSize, MAX_FILE_SIZE)); - return DataFile.ValidationResult.FILE_TOO_LARGE; + return ArbitraryDataFile.ValidationResult.FILE_TOO_LARGE; } } catch (IOException e) { @@ -198,7 +198,7 @@ public class DataFile { return ValidationResult.OK; } - public void addChunk(DataFileChunk chunk) { + public void addChunk(ArbitraryDataFileChunk chunk) { this.chunks.add(chunk); } @@ -210,7 +210,7 @@ public class DataFile { while (byteBuffer.remaining() >= TransactionTransformer.SHA256_LENGTH) { byte[] chunkDigest = new byte[TransactionTransformer.SHA256_LENGTH]; byteBuffer.get(chunkDigest); - DataFileChunk chunk = DataFileChunk.fromHash(chunkDigest); + ArbitraryDataFileChunk chunk = ArbitraryDataFileChunk.fromHash(chunkDigest); this.addChunk(chunk); } } @@ -232,7 +232,7 @@ public class DataFile { out.write(buffer, 0, numberOfBytes); out.flush(); - DataFileChunk chunk = new DataFileChunk(out.toByteArray()); + ArbitraryDataFileChunk chunk = new ArbitraryDataFileChunk(out.toByteArray()); ValidationResult validationResult = chunk.isValid(); if (validationResult == ValidationResult.OK) { this.chunks.add(chunk); @@ -266,7 +266,7 @@ public class DataFile { // Join the chunks File outputFile = new File(this.filePath); try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outputFile))) { - for (DataFileChunk chunk : this.chunks) { + for (ArbitraryDataFileChunk chunk : this.chunks) { File sourceFile = new File(chunk.filePath); BufferedInputStream in = new BufferedInputStream(new FileInputStream(sourceFile)); byte[] buffer = new byte[2048]; @@ -323,7 +323,7 @@ public class DataFile { if (this.chunks != null && this.chunks.size() > 0) { Iterator iterator = this.chunks.iterator(); while (iterator.hasNext()) { - DataFileChunk chunk = (DataFileChunk) iterator.next(); + ArbitraryDataFileChunk chunk = (ArbitraryDataFileChunk) iterator.next(); chunk.delete(); iterator.remove(); success = true; @@ -376,7 +376,7 @@ public class DataFile { } public boolean chunkExists(byte[] hash) { - for (DataFileChunk chunk : this.chunks) { + for (ArbitraryDataFileChunk chunk : this.chunks) { if (Arrays.equals(hash, chunk.getHash())) { return chunk.exists(); } @@ -389,7 +389,7 @@ public class DataFile { while (byteBuffer.remaining() >= TransactionTransformer.SHA256_LENGTH) { byte[] chunkHash = new byte[TransactionTransformer.SHA256_LENGTH]; byteBuffer.get(chunkHash); - DataFileChunk chunk = DataFileChunk.fromHash(chunkHash); + ArbitraryDataFileChunk chunk = ArbitraryDataFileChunk.fromHash(chunkHash); if (!chunk.exists()) { return false; } @@ -398,7 +398,7 @@ public class DataFile { } public boolean containsChunk(byte[] hash) { - for (DataFileChunk chunk : this.chunks) { + for (ArbitraryDataFileChunk chunk : this.chunks) { if (Arrays.equals(hash, chunk.getHash())) { return true; } @@ -419,7 +419,7 @@ public class DataFile { return this.chunks.size(); } - public List getChunks() { + public List getChunks() { return this.chunks; } @@ -432,7 +432,7 @@ public class DataFile { try { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - for (DataFileChunk chunk : this.chunks) { + for (ArbitraryDataFileChunk chunk : this.chunks) { byte[] chunkHash = chunk.digest(); if (chunkHash.length != 32) { LOGGER.info("Invalid chunk hash length: {}", chunkHash.length); @@ -499,7 +499,7 @@ public class DataFile { public String printChunks() { String outputString = ""; if (this.chunkCount() > 0) { - for (DataFileChunk chunk : this.chunks) { + for (ArbitraryDataFileChunk chunk : this.chunks) { if (outputString.length() > 0) { outputString = outputString.concat(","); } diff --git a/src/main/java/org/qortal/storage/DataFileChunk.java b/src/main/java/org/qortal/storage/ArbitraryDataFileChunk.java similarity index 69% rename from src/main/java/org/qortal/storage/DataFileChunk.java rename to src/main/java/org/qortal/storage/ArbitraryDataFileChunk.java index ebc6641e..ce94bf41 100644 --- a/src/main/java/org/qortal/storage/DataFileChunk.java +++ b/src/main/java/org/qortal/storage/ArbitraryDataFileChunk.java @@ -10,24 +10,24 @@ import java.nio.file.Path; import java.nio.file.Paths; -public class DataFileChunk extends DataFile { +public class ArbitraryDataFileChunk extends ArbitraryDataFile { - private static final Logger LOGGER = LogManager.getLogger(DataFileChunk.class); + private static final Logger LOGGER = LogManager.getLogger(ArbitraryDataFileChunk.class); - public DataFileChunk(String hash58) { + public ArbitraryDataFileChunk(String hash58) { super(hash58); } - public DataFileChunk(byte[] fileContent) { + public ArbitraryDataFileChunk(byte[] fileContent) { super(fileContent); } - public static DataFileChunk fromHash58(String hash58) { - return new DataFileChunk(hash58); + public static ArbitraryDataFileChunk fromHash58(String hash58) { + return new ArbitraryDataFileChunk(hash58); } - public static DataFileChunk fromHash(byte[] hash) { - return DataFileChunk.fromHash58(Base58.encode(hash)); + public static ArbitraryDataFileChunk fromHash(byte[] hash) { + return ArbitraryDataFileChunk.fromHash58(Base58.encode(hash)); } @Override diff --git a/src/main/java/org/qortal/storage/ArbitraryDataReader.java b/src/main/java/org/qortal/storage/ArbitraryDataReader.java index adc89f40..8cd9f262 100644 --- a/src/main/java/org/qortal/storage/ArbitraryDataReader.java +++ b/src/main/java/org/qortal/storage/ArbitraryDataReader.java @@ -8,7 +8,7 @@ import org.qortal.data.transaction.ArbitraryTransactionData.*; import org.qortal.repository.DataException; import org.qortal.repository.Repository; import org.qortal.repository.RepositoryManager; -import org.qortal.storage.DataFile.*; +import org.qortal.storage.ArbitraryDataFile.*; import org.qortal.transform.Transformer; import org.qortal.utils.Base58; import org.qortal.utils.FilesystemUtils; @@ -165,9 +165,9 @@ public class ArbitraryDataReader { private void fetchFromFileHash() { // Load data file directly from the hash - DataFile dataFile = DataFile.fromHash58(resourceId); + ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash58(resourceId); // Set filePath to the location of the DataFile - this.filePath = Paths.get(dataFile.getFilePath()); + this.filePath = Paths.get(arbitraryDataFile.getFilePath()); } private void fetchFromName() throws IllegalStateException, IOException, DataException { @@ -214,27 +214,27 @@ public class ArbitraryDataReader { } // Load data file(s) - DataFile dataFile = DataFile.fromHash(digest); - if (!dataFile.exists()) { - if (!dataFile.allChunksExist(chunkHashes)) { + ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash(digest); + if (!arbitraryDataFile.exists()) { + if (!arbitraryDataFile.allChunksExist(chunkHashes)) { // TODO: fetch them? - throw new IllegalStateException(String.format("Missing chunks for file {}", dataFile)); + throw new IllegalStateException(String.format("Missing chunks for file {}", arbitraryDataFile)); } // We have all the chunks but not the complete file, so join them - dataFile.addChunkHashes(chunkHashes); - dataFile.join(); + arbitraryDataFile.addChunkHashes(chunkHashes); + arbitraryDataFile.join(); } // If the complete file still doesn't exist then something went wrong - if (!dataFile.exists()) { - throw new IOException(String.format("File doesn't exist: %s", dataFile)); + if (!arbitraryDataFile.exists()) { + throw new IOException(String.format("File doesn't exist: %s", arbitraryDataFile)); } // Ensure the complete hash matches the joined chunks - if (!Arrays.equals(dataFile.digest(), digest)) { + if (!Arrays.equals(arbitraryDataFile.digest(), digest)) { throw new IllegalStateException("Unable to validate complete file hash"); } // Set filePath to the location of the DataFile - this.filePath = Paths.get(dataFile.getFilePath()); + this.filePath = Paths.get(arbitraryDataFile.getFilePath()); } private void decrypt() { diff --git a/src/main/java/org/qortal/storage/ArbitraryDataWriter.java b/src/main/java/org/qortal/storage/ArbitraryDataWriter.java index dc298259..19a29b45 100644 --- a/src/main/java/org/qortal/storage/ArbitraryDataWriter.java +++ b/src/main/java/org/qortal/storage/ArbitraryDataWriter.java @@ -6,7 +6,7 @@ import org.apache.logging.log4j.Logger; import org.qortal.data.transaction.ArbitraryTransactionData.*; import org.qortal.crypto.AES; import org.qortal.repository.DataException; -import org.qortal.storage.DataFile.*; +import org.qortal.storage.ArbitraryDataFile.*; import org.qortal.utils.ZipUtils; import javax.crypto.BadPaddingException; @@ -33,7 +33,7 @@ public class ArbitraryDataWriter { private Compression compression; private SecretKey aesKey; - private DataFile dataFile; + private ArbitraryDataFile arbitraryDataFile; // Intermediate paths to cleanup private Path workingPath; @@ -160,20 +160,20 @@ public class ArbitraryDataWriter { } private void validate() throws IOException { - if (this.dataFile == null) { + if (this.arbitraryDataFile == null) { throw new IOException("No file available when validating"); } - this.dataFile.setSecret(this.aesKey.getEncoded()); + this.arbitraryDataFile.setSecret(this.aesKey.getEncoded()); // Validate the file - ValidationResult validationResult = this.dataFile.isValid(); + ValidationResult validationResult = this.arbitraryDataFile.isValid(); if (validationResult != ValidationResult.OK) { - throw new IllegalStateException(String.format("File %s failed validation: %s", this.dataFile, validationResult)); + throw new IllegalStateException(String.format("File %s failed validation: %s", this.arbitraryDataFile, validationResult)); } - LOGGER.info("Whole file hash is valid: {}", this.dataFile.digest58()); + LOGGER.info("Whole file hash is valid: {}", this.arbitraryDataFile.digest58()); // Validate each chunk - for (DataFileChunk chunk : this.dataFile.getChunks()) { + for (ArbitraryDataFileChunk chunk : this.arbitraryDataFile.getChunks()) { validationResult = chunk.isValid(); if (validationResult != ValidationResult.OK) { throw new IllegalStateException(String.format("Chunk %s failed validation: %s", chunk, validationResult)); @@ -184,12 +184,12 @@ public class ArbitraryDataWriter { } private void split() throws IOException { - this.dataFile = DataFile.fromPath(this.filePath.toString()); - if (this.dataFile == null) { + this.arbitraryDataFile = ArbitraryDataFile.fromPath(this.filePath.toString()); + if (this.arbitraryDataFile == null) { throw new IOException("No file available when trying to split"); } - int chunkCount = this.dataFile.split(DataFile.CHUNK_SIZE); + int chunkCount = this.arbitraryDataFile.split(ArbitraryDataFile.CHUNK_SIZE); if (chunkCount > 0) { LOGGER.info(String.format("Successfully split into %d chunk%s", chunkCount, (chunkCount == 1 ? "" : "s"))); } @@ -218,8 +218,8 @@ public class ArbitraryDataWriter { } - public DataFile getDataFile() { - return this.dataFile; + public ArbitraryDataFile getArbitraryDataFile() { + return this.arbitraryDataFile; } } diff --git a/src/main/java/org/qortal/transaction/ArbitraryTransaction.java b/src/main/java/org/qortal/transaction/ArbitraryTransaction.java index cb9142d8..890f8d32 100644 --- a/src/main/java/org/qortal/transaction/ArbitraryTransaction.java +++ b/src/main/java/org/qortal/transaction/ArbitraryTransaction.java @@ -13,8 +13,8 @@ import org.qortal.data.transaction.TransactionData; import org.qortal.payment.Payment; import org.qortal.repository.DataException; import org.qortal.repository.Repository; -import org.qortal.storage.DataFile; -import org.qortal.storage.DataFileChunk; +import org.qortal.storage.ArbitraryDataFile; +import org.qortal.storage.ArbitraryDataFileChunk; import org.qortal.transform.TransformationException; import org.qortal.transform.transaction.ArbitraryTransactionTransformer; import org.qortal.transform.transaction.TransactionTransformer; @@ -31,7 +31,7 @@ public class ArbitraryTransaction extends Transaction { public static final int POW_BUFFER_SIZE = 8 * 1024 * 1024; // bytes public static final int POW_MIN_DIFFICULTY = 12; // leading zero bits public static final int POW_MAX_DIFFICULTY = 19; // leading zero bits - public static final long MAX_FILE_SIZE = DataFile.MAX_FILE_SIZE; + public static final long MAX_FILE_SIZE = ArbitraryDataFile.MAX_FILE_SIZE; // Constructors @@ -103,7 +103,7 @@ public class ArbitraryTransaction extends Transaction { } // Check expected length of chunk hashes - int chunkCount = (int)Math.ceil((double)arbitraryTransactionData.getSize() / (double)DataFileChunk.CHUNK_SIZE); + int chunkCount = (int)Math.ceil((double)arbitraryTransactionData.getSize() / (double) ArbitraryDataFileChunk.CHUNK_SIZE); int expectedChunkHashesSize = (chunkCount > 1) ? chunkCount * HASH_LENGTH : 0; if (chunkHashes == null && expectedChunkHashesSize > 0) { return ValidationResult.INVALID_DATA_LENGTH; @@ -121,7 +121,7 @@ public class ArbitraryTransaction extends Transaction { if (arbitraryTransactionData.getVersion() >= 5) { // Check reported length of the raw data // We should not download the raw data, so validation of that will be performed later - if (arbitraryTransactionData.getSize() > DataFile.MAX_FILE_SIZE) { + if (arbitraryTransactionData.getSize() > ArbitraryDataFile.MAX_FILE_SIZE) { return ValidationResult.INVALID_DATA_LENGTH; } } diff --git a/src/test/java/org/qortal/test/DataTests.java b/src/test/java/org/qortal/test/DataTests.java index 415025be..6dd8d66c 100644 --- a/src/test/java/org/qortal/test/DataTests.java +++ b/src/test/java/org/qortal/test/DataTests.java @@ -3,7 +3,7 @@ package org.qortal.test; import org.junit.Before; import org.junit.Test; import org.qortal.repository.DataException; -import org.qortal.storage.DataFile; +import org.qortal.storage.ArbitraryDataFile; import org.qortal.test.common.Common; import java.util.Random; @@ -20,28 +20,28 @@ public class DataTests extends Common { @Test public void testSplitAndJoin() { String dummyDataString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; - DataFile dataFile = new DataFile(dummyDataString.getBytes()); - assertTrue(dataFile.exists()); - assertEquals(62, dataFile.size()); - assertEquals("3eyjYjturyVe61grRX42bprGr3Cvw6ehTy4iknVnosDj", dataFile.digest58()); + ArbitraryDataFile arbitraryDataFile = new ArbitraryDataFile(dummyDataString.getBytes()); + assertTrue(arbitraryDataFile.exists()); + assertEquals(62, arbitraryDataFile.size()); + assertEquals("3eyjYjturyVe61grRX42bprGr3Cvw6ehTy4iknVnosDj", arbitraryDataFile.digest58()); // Split into 7 chunks, each 10 bytes long - dataFile.split(10); - assertEquals(7, dataFile.chunkCount()); + arbitraryDataFile.split(10); + assertEquals(7, arbitraryDataFile.chunkCount()); // Delete the original file - dataFile.delete(); - assertFalse(dataFile.exists()); - assertEquals(0, dataFile.size()); + arbitraryDataFile.delete(); + assertFalse(arbitraryDataFile.exists()); + assertEquals(0, arbitraryDataFile.size()); // Now rebuild the original file from the chunks - assertEquals(7, dataFile.chunkCount()); - dataFile.join(); + assertEquals(7, arbitraryDataFile.chunkCount()); + arbitraryDataFile.join(); // Validate that the original file is intact - assertTrue(dataFile.exists()); - assertEquals(62, dataFile.size()); - assertEquals("3eyjYjturyVe61grRX42bprGr3Cvw6ehTy4iknVnosDj", dataFile.digest58()); + assertTrue(arbitraryDataFile.exists()); + assertEquals(62, arbitraryDataFile.size()); + assertEquals("3eyjYjturyVe61grRX42bprGr3Cvw6ehTy4iknVnosDj", arbitraryDataFile.digest58()); } @Test @@ -50,28 +50,28 @@ public class DataTests extends Common { byte[] randomData = new byte[fileSize]; new Random().nextBytes(randomData); // No need for SecureRandom here - DataFile dataFile = new DataFile(randomData); - assertTrue(dataFile.exists()); - assertEquals(fileSize, dataFile.size()); - String originalFileDigest = dataFile.digest58(); + ArbitraryDataFile arbitraryDataFile = new ArbitraryDataFile(randomData); + assertTrue(arbitraryDataFile.exists()); + assertEquals(fileSize, arbitraryDataFile.size()); + String originalFileDigest = arbitraryDataFile.digest58(); // Split into chunks using 1MiB chunk size - dataFile.split(1 * 1024 * 1024); - assertEquals(6, dataFile.chunkCount()); + arbitraryDataFile.split(1 * 1024 * 1024); + assertEquals(6, arbitraryDataFile.chunkCount()); // Delete the original file - dataFile.delete(); - assertFalse(dataFile.exists()); - assertEquals(0, dataFile.size()); + arbitraryDataFile.delete(); + assertFalse(arbitraryDataFile.exists()); + assertEquals(0, arbitraryDataFile.size()); // Now rebuild the original file from the chunks - assertEquals(6, dataFile.chunkCount()); - dataFile.join(); + assertEquals(6, arbitraryDataFile.chunkCount()); + arbitraryDataFile.join(); // Validate that the original file is intact - assertTrue(dataFile.exists()); - assertEquals(fileSize, dataFile.size()); - assertEquals(originalFileDigest, dataFile.digest58()); + assertTrue(arbitraryDataFile.exists()); + assertEquals(fileSize, arbitraryDataFile.size()); + assertEquals(originalFileDigest, arbitraryDataFile.digest58()); } }