From 33731b969a588d3156882e27bf21caba405c82b8 Mon Sep 17 00:00:00 2001 From: CalDescent Date: Tue, 1 Feb 2022 09:04:31 +0000 Subject: [PATCH] Direct peer connections now send a file list request to the peer, rather than individually requesting every chunk for a transaction. --- .../ArbitraryDataFileListManager.java | 54 +++++++++++++++++++ .../arbitrary/ArbitraryDataFileManager.java | 33 ------------ src/main/java/org/qortal/network/Network.java | 9 +--- 3 files changed, 56 insertions(+), 40 deletions(-) diff --git a/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileListManager.java b/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileListManager.java index a1dc5d21..f4af43ef 100644 --- a/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileListManager.java +++ b/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileListManager.java @@ -304,6 +304,60 @@ public class ArbitraryDataFileListManager { return true; } + public boolean fetchArbitraryDataFileList(Peer peer, byte[] signature) { + String signature58 = Base58.encode(signature); + + // Require an NTP sync + Long now = NTP.getTime(); + if (now == null) { + return false; + } + + LOGGER.debug(String.format("Sending data file list request for signature %s to peer %s...", signature58, peer)); + + // Build request + // Use a time in the past, so that the recipient peer doesn't try and relay it + long timestamp = now - 60000L; + Message getArbitraryDataFileListMessage = new GetArbitraryDataFileListMessage(signature, timestamp, 0); + + // Save our request into requests map + Triple requestEntry = new Triple<>(signature58, null, NTP.getTime()); + + // Assign random ID to this message + int id; + do { + id = new Random().nextInt(Integer.MAX_VALUE - 1) + 1; + + // Put queue into map (keyed by message ID) so we can poll for a response + // If putIfAbsent() doesn't return null, then this ID is already taken + } while (arbitraryDataFileListRequests.put(id, requestEntry) != null); + getArbitraryDataFileListMessage.setId(id); + + // Send the request + peer.sendMessage(getArbitraryDataFileListMessage); + + // Poll to see if data has arrived + final long singleWait = 100; + long totalWait = 0; + while (totalWait < ArbitraryDataManager.ARBITRARY_REQUEST_TIMEOUT) { + try { + Thread.sleep(singleWait); + } catch (InterruptedException e) { + break; + } + + requestEntry = arbitraryDataFileListRequests.get(id); + if (requestEntry == null) + return false; + + if (requestEntry.getA() == null) + break; + + totalWait += singleWait; + } + return true; + } + public void deleteFileListRequestsForSignature(byte[] signature) { String signature58 = Base58.encode(signature); for (Iterator>> it = arbitraryDataFileListRequests.entrySet().iterator(); it.hasNext();) { diff --git a/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileManager.java b/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileManager.java index 6c5376dd..339d9123 100644 --- a/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileManager.java +++ b/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileManager.java @@ -69,22 +69,6 @@ public class ArbitraryDataFileManager { // Fetch data files by hash - public boolean fetchAllArbitraryDataFiles(Repository repository, Peer peer, byte[] signature) { - try { - TransactionData transactionData = repository.getTransactionRepository().fromSignature(signature); - if (!(transactionData instanceof ArbitraryTransactionData)) - return false; - - ArbitraryTransactionData arbitraryTransactionData = (ArbitraryTransactionData) transactionData; - - // We use null to represent all hashes associated with this transaction - return this.fetchArbitraryDataFiles(repository, peer, signature, arbitraryTransactionData, null); - - } catch (DataException e) {} - - return false; - } - public boolean fetchArbitraryDataFiles(Repository repository, Peer peer, byte[] signature, @@ -95,23 +79,6 @@ public class ArbitraryDataFileManager { ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash(arbitraryTransactionData.getData(), signature); byte[] metadataHash = arbitraryTransactionData.getMetadataHash(); arbitraryDataFile.setMetadataHash(metadataHash); - - // If hashes are null, we will treat this to mean all data hashes associated with this file - if (hashes == null) { - if (metadataHash == null) { - // This transaction has no metadata/chunks, so use the main file hash - hashes = Arrays.asList(arbitraryDataFile.getHash()); - } - else if (!arbitraryDataFile.getMetadataFile().exists()) { - // We don't have the metadata file yet, so request it - hashes = Arrays.asList(arbitraryDataFile.getMetadataFile().getHash()); - } - else { - // Add the chunk hashes - hashes = arbitraryDataFile.getChunkHashes(); - } - } - boolean receivedAtLeastOneFile = false; // Now fetch actual data from this peer diff --git a/src/main/java/org/qortal/network/Network.java b/src/main/java/org/qortal/network/Network.java index dde82112..2f5d9bd9 100644 --- a/src/main/java/org/qortal/network/Network.java +++ b/src/main/java/org/qortal/network/Network.java @@ -6,7 +6,7 @@ import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters; import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters; import org.qortal.block.BlockChain; import org.qortal.controller.Controller; -import org.qortal.controller.arbitrary.ArbitraryDataFileManager; +import org.qortal.controller.arbitrary.ArbitraryDataFileListManager; import org.qortal.controller.arbitrary.ArbitraryDataManager; import org.qortal.crypto.Crypto; import org.qortal.data.block.BlockData; @@ -307,12 +307,7 @@ public class Network { return false; } - try (final Repository repository = RepositoryManager.getRepository()) { - return ArbitraryDataFileManager.getInstance().fetchAllArbitraryDataFiles(repository, connectedPeer, signature); - } catch (DataException e) { - LOGGER.info("Unable to fetch arbitrary data files"); - } - return false; + return ArbitraryDataFileListManager.getInstance().fetchArbitraryDataFileList(connectedPeer, signature); } /**