From 2165c87b9df8c7f1c98625b0262ee2a53af6136f Mon Sep 17 00:00:00 2001 From: catbref Date: Thu, 13 Aug 2020 13:45:06 +0100 Subject: [PATCH] Fix race condition between Network.start() and Controller calling Network.prunePeers() Modified synchronized Lists to be final. Moved some initializers out of constructor. --- src/main/java/org/qortal/network/Network.java | 44 ++++++------------- 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/src/main/java/org/qortal/network/Network.java b/src/main/java/org/qortal/network/Network.java index c7f48ed8..99ea7210 100644 --- a/src/main/java/org/qortal/network/Network.java +++ b/src/main/java/org/qortal/network/Network.java @@ -50,7 +50,6 @@ import org.qortal.repository.DataException; import org.qortal.repository.Repository; import org.qortal.repository.RepositoryManager; import org.qortal.settings.Settings; -import org.qortal.transform.Transformer; import org.qortal.utils.ExecuteProduceConsume; // import org.qortal.utils.ExecutorDumper; import org.qortal.utils.ExecuteProduceConsume.StatsSnapshot; @@ -91,15 +90,16 @@ public class Network { public static final int MAX_SIGNATURES_PER_REPLY = 500; public static final int MAX_BLOCK_SUMMARIES_PER_REPLY = 500; - private final Ed25519PrivateKeyParameters edPrivateKeyParams; - private final Ed25519PublicKeyParameters edPublicKeyParams; - private final String ourNodeId; + // Generate our node keys / ID + private final Ed25519PrivateKeyParameters edPrivateKeyParams = new Ed25519PrivateKeyParameters(new SecureRandom()); + private final Ed25519PublicKeyParameters edPublicKeyParams = edPrivateKeyParams.generatePublicKey(); + private final String ourNodeId = Crypto.toNodeAddress(edPublicKeyParams.getEncoded()); private final int maxMessageSize; - private List allKnownPeers; - private List connectedPeers; - private List selfPeers; + private final List allKnownPeers = new ArrayList<>(); + private final List connectedPeers = new ArrayList<>(); + private final List selfPeers = new ArrayList<>(); private ExecuteProduceConsume networkEPC; private Selector channelSelector; @@ -108,39 +108,21 @@ public class Network { private int minOutboundPeers; private int maxPeers; - private long nextConnectTaskTimestamp; + private long nextConnectTaskTimestamp = 0L; // ms - try first connect once NTP syncs - private ExecutorService broadcastExecutor; - private long nextBroadcastTimestamp; + private ExecutorService broadcastExecutor = Executors.newCachedThreadPool(); + private long nextBroadcastTimestamp = 0L; // ms - try first broadcast once NTP syncs - private Lock mergePeersLock; + private final Lock mergePeersLock = new ReentrantLock(); // Constructors private Network() { - connectedPeers = new ArrayList<>(); - selfPeers = new ArrayList<>(); - - // Generate our ID - byte[] seed = new byte[Transformer.PRIVATE_KEY_LENGTH]; - new SecureRandom().nextBytes(seed); - - edPrivateKeyParams = new Ed25519PrivateKeyParameters(seed, 0); - edPublicKeyParams = edPrivateKeyParams.generatePublicKey(); - ourNodeId = Crypto.toNodeAddress(edPublicKeyParams.getEncoded()); - maxMessageSize = 4 + 1 + 4 + BlockChain.getInstance().getMaxBlockSize(); minOutboundPeers = Settings.getInstance().getMinOutboundPeers(); maxPeers = Settings.getInstance().getMaxPeers(); - nextConnectTaskTimestamp = 0; // First connect once NTP syncs - - broadcastExecutor = Executors.newCachedThreadPool(); - nextBroadcastTimestamp = 0; // First broadcast once NTP syncs - - mergePeersLock = new ReentrantLock(); - // We'll use a cached thread pool but with more aggressive timeout. ExecutorService networkExecutor = new ThreadPoolExecutor(1, Settings.getInstance().getMaxNetworkThreadPoolSize(), @@ -177,7 +159,9 @@ public class Network { // Load all known peers from repository try (final Repository repository = RepositoryManager.getRepository()) { - allKnownPeers = repository.getNetworkRepository().getAllPeers(); + synchronized (this.allKnownPeers) { + this.allKnownPeers.addAll(repository.getNetworkRepository().getAllPeers()); + } } // Start up first networking thread