diff --git a/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileManager.java b/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileManager.java index 1b1cb945..2b0b8143 100644 --- a/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileManager.java +++ b/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileManager.java @@ -159,7 +159,7 @@ public class ArbitraryDataFileManager { // but only if these files are in accordance with our storage policy if (ArbitraryDataStorageManager.getInstance().canStoreData(arbitraryTransactionData)) { // 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); } } diff --git a/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataManager.java b/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataManager.java index e2d62f6a..a0ef02bb 100644 --- a/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataManager.java +++ b/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataManager.java @@ -43,6 +43,9 @@ public class ArbitraryDataManager extends Thread { /** Maximum time to hold information about an in-progress relay */ 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 final Object peerDataLock = new Object(); @@ -369,7 +372,7 @@ public class ArbitraryDataManager extends Thread { // Broadcast the list, using null to represent our peer address 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); } 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 // network in case some peers haven't received it yet if (containsNewEntry) { - LOGGER.debug("Rebroadcasting arbitrary signature list for peer {}", peerAddress); - Network.getInstance().broadcast(broadcastPeer -> broadcastPeer == peer ? null : arbitrarySignaturesMessage); + int requestHops = arbitrarySignaturesMessage.getRequestHops(); + 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 { // Don't rebroadcast as otherwise we could get into a loop } diff --git a/src/main/java/org/qortal/network/message/ArbitrarySignaturesMessage.java b/src/main/java/org/qortal/network/message/ArbitrarySignaturesMessage.java index 379eeb47..16af9649 100644 --- a/src/main/java/org/qortal/network/message/ArbitrarySignaturesMessage.java +++ b/src/main/java/org/qortal/network/message/ArbitrarySignaturesMessage.java @@ -2,7 +2,6 @@ package org.qortal.network.message; import com.google.common.primitives.Ints; import org.qortal.data.network.PeerData; -import org.qortal.transaction.DeployAtTransaction; import org.qortal.transform.TransformationException; import org.qortal.transform.Transformer; import org.qortal.utils.Serialization; @@ -19,16 +18,18 @@ public class ArbitrarySignaturesMessage extends Message { private static final int SIGNATURE_LENGTH = Transformer.SIGNATURE_LENGTH; private String peerAddress; + private int requestHops; private List signatures; - public ArbitrarySignaturesMessage(String peerAddress, List signatures) { - this(-1, peerAddress, signatures); + public ArbitrarySignaturesMessage(String peerAddress, int requestHops, List signatures) { + this(-1, peerAddress, requestHops, signatures); } - private ArbitrarySignaturesMessage(int id, String peerAddress, List signatures) { + private ArbitrarySignaturesMessage(int id, String peerAddress, int requestHops, List signatures) { super(id, MessageType.ARBITRARY_SIGNATURES); this.peerAddress = peerAddress; + this.requestHops = requestHops; this.signatures = signatures; } @@ -40,9 +41,19 @@ public class ArbitrarySignaturesMessage extends Message { 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 { String peerAddress = Serialization.deserializeSizedString(bytes, PeerData.MAX_PEER_ADDRESS_SIZE); + int requestHops = bytes.getInt(); + int signatureCount = bytes.getInt(); if (bytes.remaining() != signatureCount * SIGNATURE_LENGTH) @@ -55,7 +66,7 @@ public class ArbitrarySignaturesMessage extends Message { signatures.add(signature); } - return new ArbitrarySignaturesMessage(id, peerAddress, signatures); + return new ArbitrarySignaturesMessage(id, peerAddress, requestHops, signatures); } @Override @@ -65,6 +76,8 @@ public class ArbitrarySignaturesMessage extends Message { Serialization.serializeSizedString(bytes, this.peerAddress); + bytes.write(Ints.toByteArray(this.requestHops)); + bytes.write(Ints.toByteArray(this.signatures.size())); for (byte[] signature : this.signatures) diff --git a/src/main/java/org/qortal/transaction/ArbitraryTransaction.java b/src/main/java/org/qortal/transaction/ArbitraryTransaction.java index d8740351..ddb58b0e 100644 --- a/src/main/java/org/qortal/transaction/ArbitraryTransaction.java +++ b/src/main/java/org/qortal/transaction/ArbitraryTransaction.java @@ -228,7 +228,7 @@ public class ArbitraryTransaction extends Transaction { if (ArbitraryDataStorageManager.getInstance().canStoreData(arbitraryTransactionData)) { // Use a null peer address to indicate our own 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); } }