From c9356d0ff522527a4011ae196a2efd0f7cc2f7e0 Mon Sep 17 00:00:00 2001 From: CalDescent Date: Fri, 29 Oct 2021 16:16:58 +0100 Subject: [PATCH] Re-broadcast the arbitrary signatures message if it contains new data, so that the message finds its way to all online peers. --- .../arbitrary/ArbitraryDataManager.java | 27 +++++++++++++++-- .../org/qortal/data/network/PeerData.java | 2 ++ .../message/ArbitrarySignaturesMessage.java | 30 ++++++++++++++----- 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataManager.java b/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataManager.java index b9526919..9541a17e 100644 --- a/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataManager.java +++ b/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataManager.java @@ -558,7 +558,8 @@ public class ArbitraryDataManager extends Thread { } // We also need to broadcast to the network that we are now hosting files for this transaction - Message newArbitrarySignatureMessage = new ArbitrarySignaturesMessage(Arrays.asList(signature)); + // Use a null peer address to indicate our own + Message newArbitrarySignatureMessage = new ArbitrarySignaturesMessage(null, Arrays.asList(signature)); Network.getInstance().broadcast(broadcastPeer -> newArbitrarySignatureMessage); } @@ -666,9 +667,18 @@ public class ArbitraryDataManager extends Thread { public void onNetworkArbitrarySignaturesMessage(Peer peer, Message message) { LOGGER.info("Received arbitrary signature list from peer {}", peer); + ArbitrarySignaturesMessage arbitrarySignaturesMessage = (ArbitrarySignaturesMessage) message; List signatures = arbitrarySignaturesMessage.getSignatures(); + String peerAddress = peer.getPeerData().getAddress().toString(); + if (arbitrarySignaturesMessage.getPeerAddress() != null) { + // This message is about a different peer than the one that sent it + peerAddress = arbitrarySignaturesMessage.getPeerAddress(); + } + + boolean containsNewEntry = false; + try (final Repository repository = RepositoryManager.getRepository()) { for (byte[] signature : signatures) { @@ -678,13 +688,26 @@ public class ArbitraryDataManager extends Thread { if (existingEntry == null) { // We haven't got a record of this mapping yet, so add it - LOGGER.info("Adding arbitrary peer: {} for signature {}", peer.getPeerData().getAddress().toString(), Base58.encode(signature)); + LOGGER.info("Adding arbitrary peer: {} for signature {}", peerAddress, Base58.encode(signature)); ArbitraryPeerData arbitraryPeerData = new ArbitraryPeerData(signature, peer); repository.getArbitraryRepository().save(arbitraryPeerData); repository.saveChanges(); + + // Remember that this data is new, so that it can be re-broadcast later + containsNewEntry = true; } } + // If at least one signature in this batch was new to us, we should re-broadcast the message to the + // network in case some peers haven't received it yet + if (containsNewEntry) { + LOGGER.info("Rebroadcasting arbitrary signature list for peer {}", peerAddress); + Network.getInstance().broadcast(broadcastPeer -> arbitrarySignaturesMessage); + } + else { + // Don't re-broadcast as otherwise we could get into a loop + } + // If anything needed saving, it would already have called saveChanges() above repository.discardChanges(); } catch (DataException e) { diff --git a/src/main/java/org/qortal/data/network/PeerData.java b/src/main/java/org/qortal/data/network/PeerData.java index 3362ff11..09982c00 100644 --- a/src/main/java/org/qortal/data/network/PeerData.java +++ b/src/main/java/org/qortal/data/network/PeerData.java @@ -13,6 +13,8 @@ import io.swagger.v3.oas.annotations.media.Schema; @XmlAccessorType(XmlAccessType.FIELD) public class PeerData { + public static final int MAX_PEER_ADDRESS_SIZE = 255; + // Properties // Don't expose this via JAXB - use pretty getter instead diff --git a/src/main/java/org/qortal/network/message/ArbitrarySignaturesMessage.java b/src/main/java/org/qortal/network/message/ArbitrarySignaturesMessage.java index 70a26775..379eeb47 100644 --- a/src/main/java/org/qortal/network/message/ArbitrarySignaturesMessage.java +++ b/src/main/java/org/qortal/network/message/ArbitrarySignaturesMessage.java @@ -1,7 +1,11 @@ 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; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -14,36 +18,44 @@ public class ArbitrarySignaturesMessage extends Message { private static final int SIGNATURE_LENGTH = Transformer.SIGNATURE_LENGTH; + private String peerAddress; private List signatures; - public ArbitrarySignaturesMessage(List signatures) { - this(-1, signatures); + public ArbitrarySignaturesMessage(String peerAddress, List signatures) { + this(-1, peerAddress, signatures); } - private ArbitrarySignaturesMessage(int id, List signatures) { + private ArbitrarySignaturesMessage(int id, String peerAddress, List signatures) { super(id, MessageType.ARBITRARY_SIGNATURES); + this.peerAddress = peerAddress; this.signatures = signatures; } + public String getPeerAddress() { + return this.peerAddress; + } + public List getSignatures() { return this.signatures; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { - int count = bytes.getInt(); + public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException, TransformationException { + String peerAddress = Serialization.deserializeSizedString(bytes, PeerData.MAX_PEER_ADDRESS_SIZE); - if (bytes.remaining() != count * SIGNATURE_LENGTH) + int signatureCount = bytes.getInt(); + + if (bytes.remaining() != signatureCount * SIGNATURE_LENGTH) return null; List signatures = new ArrayList<>(); - for (int i = 0; i < count; ++i) { + for (int i = 0; i < signatureCount; ++i) { byte[] signature = new byte[SIGNATURE_LENGTH]; bytes.get(signature); signatures.add(signature); } - return new ArbitrarySignaturesMessage(id, signatures); + return new ArbitrarySignaturesMessage(id, peerAddress, signatures); } @Override @@ -51,6 +63,8 @@ public class ArbitrarySignaturesMessage extends Message { try { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + Serialization.serializeSizedString(bytes, this.peerAddress); + bytes.write(Ints.toByteArray(this.signatures.size())); for (byte[] signature : this.signatures)