Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Move to fully connected network #13010

Merged
merged 23 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f23c2ac
12984 use peers for Network component
kfa-aguda Apr 24, 2024
e27c958
12984 use peers for Network component
kfa-aguda Apr 25, 2024
5297e23
Revert "12984 use peers for Network component"
kfa-aguda Apr 25, 2024
9793eae
12984 use peers for Network component
kfa-aguda Apr 25, 2024
2d70913
12984 use peers for Network component
kfa-aguda Apr 25, 2024
5368df8
12984 use peers for Network component
kfa-aguda Apr 25, 2024
3808eae
12984 use peers for Network component
kfa-aguda Apr 30, 2024
e46101c
Merge branch 'develop' into 12984-no-addressBook
kfa-aguda Apr 30, 2024
79b929b
12984 use peers for Network component
kfa-aguda Apr 30, 2024
74d668d
12984 use peers for Network component
kfa-aguda Apr 30, 2024
dd516d0
12984 use peers for Network component
kfa-aguda Apr 30, 2024
01a3870
12984 use peers for Network component
kfa-aguda May 24, 2024
28830a4
12984 use peers for Network component
kfa-aguda May 24, 2024
490ce6e
Merge branch 'develop' into 12984-no-addressBook
kfa-aguda May 24, 2024
284ff3f
12984 use peers for Network component
kfa-aguda May 24, 2024
1dce814
12984 use peers for Network component
kfa-aguda May 24, 2024
b3de315
spotless
kfa-aguda May 24, 2024
06b7dcb
adjust neighbours
kfa-aguda May 24, 2024
3343437
Merge branch 'develop' into 12984-no-addressBook
kfa-aguda May 24, 2024
a60dec7
adjust neighbours
kfa-aguda May 29, 2024
c602e58
adjust neighbours
kfa-aguda Jun 3, 2024
024e0f7
Merge branch 'develop' into 12984-no-addressBook
kfa-aguda Jun 3, 2024
c25245b
adjust neighbours
kfa-aguda Jun 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1025,7 +1025,6 @@ public Gossip buildGossip() {
if (gossip == null) {
gossip = new SyncGossip(
blocks.platformContext(),
blocks.randomBuilder().buildNonCryptographicRandom(),
AdHocThreadManager.getStaticThreadManager(),
blocks.keysAndCerts(),
blocks.initialAddressBook(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import com.swirlds.common.merkle.synchronization.config.ReconnectConfig;
import com.swirlds.common.platform.NodeId;
import com.swirlds.platform.network.RandomGraph;
import com.swirlds.platform.network.topology.NetworkTopology;
import com.swirlds.platform.system.address.AddressBook;
import com.swirlds.platform.system.status.StatusActionSubmitter;
import com.swirlds.platform.system.status.actions.FallenBehindAction;
Expand All @@ -38,11 +38,12 @@ public class FallenBehindManagerImpl implements FallenBehindManager {
/**
* a set of all neighbors of this node
*/
private final HashSet<NodeId> allNeighbors;
private final Set<NodeId> allNeighbors;
/**
* the number of neighbors we have
*/
private final int numNeighbors;

/**
* set of neighbors who report that this node has fallen behind
*/
Expand Down Expand Up @@ -72,23 +73,19 @@ public class FallenBehindManagerImpl implements FallenBehindManager {
public FallenBehindManagerImpl(
@NonNull final AddressBook addressBook,
@NonNull final NodeId selfId,
@NonNull final RandomGraph connectionGraph,
@NonNull final NetworkTopology topology,
@NonNull final StatusActionSubmitter statusActionSubmitter,
@NonNull final Runnable fallenBehindCallback,
@NonNull final ReconnectConfig config) {
Objects.requireNonNull(addressBook, "addressBook");
Objects.requireNonNull(selfId, "selfId");
Objects.requireNonNull(connectionGraph, "connectionGraph");
Objects.requireNonNull(topology, "topology");

notYetReportFallenBehind = ConcurrentHashMap.newKeySet();
reportFallenBehind = new HashSet<>();
allNeighbors = new HashSet<>();
/* an array with all the neighbor ids */
final int[] neighbors = connectionGraph.getNeighbors(addressBook.getIndexOfNodeId(selfId));
numNeighbors = neighbors.length;
for (final int neighbor : neighbors) {
allNeighbors.add(addressBook.getNodeId(neighbor));
}
allNeighbors = topology.getNeighbors();
numNeighbors = allNeighbors.size();

this.statusActionSubmitter = Objects.requireNonNull(statusActionSubmitter);
this.fallenBehindCallback =
Objects.requireNonNull(fallenBehindCallback, "fallenBehindCallback must not be null");
Expand Down Expand Up @@ -137,7 +134,7 @@ public synchronized List<NodeId> getNeighborsForReconnect() {
}

@Override
public boolean shouldReconnectFrom(final NodeId peerId) {
public boolean shouldReconnectFrom(@NonNull final NodeId peerId) {
if (!hasFallenBehind()) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
Expand Down Expand Up @@ -156,7 +155,6 @@ public class SyncGossip implements ConnectionTracker, Gossip {
* Builds the gossip engine, depending on which flavor is requested in the configuration.
*
* @param platformContext the platform context
* @param random a source of randomness, does not need to be cryptographically secure
* @param threadManager the thread manager
* @param keysAndCerts private keys and public certificates
* @param addressBook the current address book
Expand All @@ -173,7 +171,6 @@ public class SyncGossip implements ConnectionTracker, Gossip {
*/
public SyncGossip(
@NonNull final PlatformContext platformContext,
@NonNull final Random random,
@NonNull final ThreadManager threadManager,
@NonNull final KeysAndCerts keysAndCerts,
@NonNull final AddressBook addressBook,
Expand All @@ -199,9 +196,9 @@ public SyncGossip(
final ThreadConfig threadConfig = platformContext.getConfiguration().getConfigData(ThreadConfig.class);

final BasicConfig basicConfig = platformContext.getConfiguration().getConfigData(BasicConfig.class);

topology = new StaticTopology(random, addressBook, selfId, basicConfig.numConnections());
final List<PeerInfo> peers = Utilities.createPeerInfoList(addressBook, selfId);

topology = new StaticTopology(peers, selfId);
final NetworkPeerIdentifier peerIdentifier = new NetworkPeerIdentifier(platformContext, peers);
final SocketFactory socketFactory =
NetworkUtils.createSocketFactory(selfId, peers, keysAndCerts, platformContext.getConfiguration());
Expand Down Expand Up @@ -231,7 +228,7 @@ public SyncGossip(
fallenBehindManager = new FallenBehindManagerImpl(
addressBook,
selfId,
topology.getConnectionGraph(),
topology,
statusActionSubmitter,
() -> getReconnectController().start(),
platformContext.getConfiguration().getConfigData(ReconnectConfig.class));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@
package com.swirlds.platform.network.topology;

import com.swirlds.common.platform.NodeId;
import com.swirlds.platform.network.RandomGraph;
import java.util.List;
import java.util.function.Predicate;
import java.util.Set;

/**
* Holds information about the topology of the network
Expand All @@ -44,17 +42,7 @@ public interface NetworkTopology {
boolean shouldConnectToMe(NodeId nodeId);

/**
* @return a list of all peers this node should be connected to
* @return a Set of all peers this node should be connected to
*/
List<NodeId> getNeighbors();

/**
* @return a list of peers this node should be connected to with the applied filter
*/
List<NodeId> getNeighbors(final Predicate<NodeId> filter);

/**
* @return the underlying graph on which this topology is based on
*/
RandomGraph getConnectionGraph();
Set<NodeId> getNeighbors();
}
kfa-aguda marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -17,108 +17,55 @@
package com.swirlds.platform.network.topology;

import com.swirlds.common.platform.NodeId;
import com.swirlds.platform.network.RandomGraph;
import com.swirlds.platform.system.address.AddressBook;
import com.swirlds.platform.network.PeerInfo;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.function.Predicate;
import java.util.Set;

/**
* A bidirectional topology that never changes.
* A fully connected topology that never changes.
*/
public class StaticTopology implements NetworkTopology {
private static final long SEED = 0;

private final NodeId selfId;
/**
* Two nodes are neighbors if their indexes in the address book are neighbors in the connection graph.
*/
private final AddressBook addressBook;
private final Set<NodeId> nodeIds = new HashSet<>();

private final RandomGraph connectionGraph;
private final NodeId selfId;

/**
* Constructor.
*
* @param random a source of randomness, used to chose random neighbors, does not need to be
* cryptographically secure
* @param addressBook the current address book
* @param peers the set of peers in the network
* @param selfId the ID of this node
* @param numberOfNeighbors the number of neighbors each node should have
*/
public StaticTopology(
@NonNull final Random random,
@NonNull final AddressBook addressBook,
@NonNull final NodeId selfId,
final int numberOfNeighbors) {
this.addressBook = Objects.requireNonNull(addressBook, "addressBook must not be null");
this.selfId = Objects.requireNonNull(selfId, "selfId must not be null");
this.connectionGraph = new RandomGraph(random, addressBook.getSize(), numberOfNeighbors, SEED);

if (!addressBook.contains(selfId)) {
throw new IllegalArgumentException("Address book does not contain selfId");
}
}

/**
* {@inheritDoc}
*/
@Override
public List<NodeId> getNeighbors() {
return getNeighbors((nodeId -> true));
public StaticTopology(@NonNull final List<PeerInfo> peers, @NonNull final NodeId selfId) {
Objects.requireNonNull(peers);
Objects.requireNonNull(selfId);
peers.forEach(peer -> nodeIds.add(peer.nodeId()));
this.selfId = selfId;
}

/**
* {@inheritDoc}
*/
@Override
public List<NodeId> getNeighbors(final Predicate<NodeId> filter) {
final int selfIndex = addressBook.getIndexOfNodeId(selfId);
return Arrays.stream(connectionGraph.getNeighbors(selfIndex))
.mapToObj(addressBook::getNodeId)
.filter(filter)
.toList();
public Set<NodeId> getNeighbors() {
return nodeIds;
}

/**
* {@inheritDoc}
*/
@Override
public boolean shouldConnectToMe(final NodeId nodeId) {
return isNeighbor(nodeId) && addressBook.getIndexOfNodeId(nodeId) < addressBook.getIndexOfNodeId(selfId);
}

/**
* Queries the topology on whether this node is my neighbor
*
* @param nodeId the ID of the node being queried
* @return true if this node is my neighbor, false if not
*/
private boolean isNeighbor(final NodeId nodeId) {
if (!addressBook.contains(nodeId)) {
return false;
}
final int selfIndex = addressBook.getIndexOfNodeId(selfId);
final int nodeIndex = addressBook.getIndexOfNodeId(nodeId);
return connectionGraph.isAdjacent(selfIndex, nodeIndex);
return nodeIds.contains(nodeId) && nodeId.id() < selfId.id();
}

/**
* {@inheritDoc}
*/
@Override
public boolean shouldConnectTo(final NodeId nodeId) {
return isNeighbor(nodeId) && addressBook.getIndexOfNodeId(nodeId) > addressBook.getIndexOfNodeId(selfId);
}

/**
* {@inheritDoc}
*/
@Override
public RandomGraph getConnectionGraph() {
return connectionGraph;
return nodeIds.contains(nodeId) && nodeId.id() > selfId.id();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public class DummyHashgraph {
isInCriticalQuorum = new HashMap<>();
numUserTransEvents = 0;
lastRoundReceivedAllTransCons = 0;
addressBook = RandomAddressBookBuilder.create(random).withSize(100).build();
addressBook = RandomAddressBookBuilder.create(random).withSize(41).build();
this.selfId = addressBook.getNodeId(selfIndex);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import static com.swirlds.common.test.fixtures.RandomUtils.getRandomPrintSeed;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
Expand All @@ -34,7 +35,9 @@
import com.swirlds.platform.eventhandling.EventConfig_;
import com.swirlds.platform.gossip.FallenBehindManagerImpl;
import com.swirlds.platform.gossip.sync.SyncManagerImpl;
import com.swirlds.platform.network.RandomGraph;
import com.swirlds.platform.network.PeerInfo;
import com.swirlds.platform.network.topology.NetworkTopology;
import com.swirlds.platform.network.topology.StaticTopology;
import com.swirlds.platform.pool.TransactionPoolNexus;
import com.swirlds.platform.system.address.AddressBook;
import com.swirlds.platform.system.status.StatusActionSubmitter;
Expand All @@ -57,7 +60,6 @@ private static class SyncManagerTestData {
public AddressBook addressBook;
public NodeId selfId;
public TransactionPoolNexus transactionPoolNexus;
public RandomGraph connectionGraph;
public SyncManagerImpl syncManager;
public Configuration configuration;

Expand All @@ -71,23 +73,24 @@ public SyncManagerTestData() {

this.addressBook = hashgraph.getAddressBook();
this.selfId = addressBook.getNodeId(0);
final int size = addressBook.getSize();

connectionGraph = new RandomGraph(random, size, 40, 0);
configuration = new TestConfigBuilder()
.withValue(ReconnectConfig_.FALLEN_BEHIND_THRESHOLD, "0.25")
.withValue(EventConfig_.EVENT_INTAKE_QUEUE_THROTTLE_SIZE, "100")
.getOrCreateConfig();
final ReconnectConfig reconnectConfig = configuration.getConfigData(ReconnectConfig.class);
final EventConfig eventConfig = configuration.getConfigData(EventConfig.class);

final List<PeerInfo> peers = Utilities.createPeerInfoList(addressBook, selfId);
final NetworkTopology topology = new StaticTopology(peers, selfId);

syncManager = new SyncManagerImpl(
platformContext,
hashgraph::getEventIntakeQueueSize,
new FallenBehindManagerImpl(
addressBook,
selfId,
connectionGraph,
topology,
mock(StatusActionSubmitter.class),
() -> {},
reconnectConfig),
Expand All @@ -103,24 +106,24 @@ public SyncManagerTestData() {
void basicTest() {
final SyncManagerTestData test = new SyncManagerTestData();

final int[] neighbors = test.connectionGraph.getNeighbors(0);
final List<PeerInfo> peers = Utilities.createPeerInfoList(test.addressBook, test.selfId);

// we should not think we have fallen behind initially
assertFalse(test.syncManager.hasFallenBehind());
// should be null as we have no indication of falling behind
assertNull(test.syncManager.getNeededForFallenBehind());

// neighbors 0 and 1 report fallen behind
test.syncManager.reportFallenBehind(test.addressBook.getNodeId(neighbors[0]));
test.syncManager.reportFallenBehind(test.addressBook.getNodeId(neighbors[1]));
test.syncManager.reportFallenBehind(peers.get(0).nodeId());
test.syncManager.reportFallenBehind(peers.get(1).nodeId());

// we still dont have enough reports that we have fallen behind, we need more than [fallenBehindThreshold] of
// the neighbors
assertFalse(test.syncManager.hasFallenBehind());

// add more reports
for (int i = 2; i < 10; i++) {
test.syncManager.reportFallenBehind(test.addressBook.getNodeId(neighbors[i]));
test.syncManager.reportFallenBehind(peers.get(i).nodeId());
}

// we are still missing 1 report
Expand All @@ -131,12 +134,12 @@ void basicTest() {
for (final NodeId nodeId : list) {
// none of the nodes we need to call should be those who already reported we have fallen behind
for (int i = 0; i < 10; i++) {
assertTrue(test.addressBook.getIndexOfNodeId(nodeId) != neighbors[i]);
assertNotEquals(nodeId.id(), peers.get(i).nodeId().id());
}
}

// add the report that will go over the [fallenBehindThreshold]
test.syncManager.reportFallenBehind(test.addressBook.getNodeId(neighbors[10]));
test.syncManager.reportFallenBehind(peers.get(10).nodeId());

// we should now say we have fallen behind
assertTrue(test.syncManager.hasFallenBehind());
Expand Down