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 11 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 @@ -193,9 +193,9 @@ protected 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(random, peers, selfId, basicConfig.numConnections());
kfa-aguda marked this conversation as resolved.
Show resolved Hide resolved
final NetworkPeerIdentifier peerIdentifier = new NetworkPeerIdentifier(platformContext, peers);
final SocketFactory socketFactory =
NetworkUtils.createSocketFactory(selfId, peers, keysAndCerts, platformContext.getConfiguration());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.swirlds.common.threading.locks.locked.LockedResource;
import com.swirlds.platform.network.connection.NotConnectedConnection;
import com.swirlds.platform.network.connectivity.OutboundConnectionCreator;
import java.util.Objects;

/**
* Manages a connection that is initiated by this node. If the connection in use is broken, it will try to establish a
Expand All @@ -46,7 +47,7 @@ public OutboundConnectionManager(final NodeId peerId, final OutboundConnectionCr
@Override
public Connection waitForConnection() {
try (final LockedResource<Connection> resource = lock.lock()) {
while (!resource.getResource().connected()) {
while (!Objects.requireNonNull(resource.getResource()).connected()) {
kfa-aguda marked this conversation as resolved.
Show resolved Hide resolved
resource.getResource().disconnect();
resource.setResource(connectionCreator.createConnection(peerId));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@

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,14 +43,9 @@ 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);
Set<NodeId> getNeighbors();

/**
* @return the underlying graph on which this topology is based on
Expand Down
kfa-aguda marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -17,78 +17,64 @@
package com.swirlds.platform.network.topology;

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

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

private final NodeId selfId;
/** nodes are mapped so lookups are efficient. **/
private Map<NodeId, Long> peerNodeToIdMap = new HashMap<>();
kfa-aguda marked this conversation as resolved.
Show resolved Hide resolved

/**
* Two nodes are neighbors if their indexes in the address book are neighbors in the connection graph.
* Two nodes are neighbors if their node indexes are neighbors in the connection graph.
*/
private final AddressBook addressBook;

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 List<PeerInfo> peers,
kfa-aguda marked this conversation as resolved.
Show resolved Hide resolved
@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));
this.peerNodeToIdMap = map(peers);
this.selfId = selfId;
this.connectionGraph = new RandomGraph(random, peers.size() + 1, numberOfNeighbors, SEED);
}

/**
* {@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 peerNodeToIdMap.keySet();
kfa-aguda marked this conversation as resolved.
Show resolved Hide resolved
}

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

/**
Expand All @@ -98,20 +84,15 @@ public boolean shouldConnectToMe(final NodeId nodeId) {
* @return true if this node is my neighbor, false if not
*/
private boolean isNeighbor(final NodeId nodeId) {
kfa-aguda marked this conversation as resolved.
Show resolved Hide resolved
if (!addressBook.contains(nodeId)) {
return false;
}
final int selfIndex = addressBook.getIndexOfNodeId(selfId);
final int nodeIndex = addressBook.getIndexOfNodeId(nodeId);
return connectionGraph.isAdjacent(selfIndex, nodeIndex);
return peerNodeToIdMap.containsKey(nodeId);
kfa-aguda marked this conversation as resolved.
Show resolved Hide resolved
}

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

/**
Expand All @@ -121,4 +102,19 @@ public boolean shouldConnectTo(final NodeId nodeId) {
public RandomGraph getConnectionGraph() {
return connectionGraph;
}

/**
* Maps the list of peers to a map of node IDs to their index in the peer list
* and populates the peerNodesList with the node IDs
*
* @param peers the list of peers
* @return the map of node IDs to their peer Id
*/
@NonNull
private Map<NodeId, Long> map(@NonNull final List<PeerInfo> peers) {
for (final PeerInfo peer : peers) {
peerNodeToIdMap.put(peer.nodeId(), peer.nodeId().id());
kfa-aguda marked this conversation as resolved.
Show resolved Hide resolved
}
return peerNodeToIdMap;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@

import com.swirlds.common.platform.NodeId;
import com.swirlds.common.test.fixtures.RandomUtils;
import com.swirlds.platform.Utilities;
import com.swirlds.platform.network.Connection;
import com.swirlds.platform.network.ConnectionManager;
import com.swirlds.platform.network.PeerInfo;
import com.swirlds.platform.network.connectivity.OutboundConnectionCreator;
import com.swirlds.platform.network.topology.NetworkTopology;
import com.swirlds.platform.network.topology.StaticConnectionManagers;
import com.swirlds.platform.network.topology.StaticTopology;
import com.swirlds.platform.system.address.AddressBook;
Expand Down Expand Up @@ -57,9 +60,12 @@ void testShouldConnectToMe(final int numNodes, final int numNeighbors) throws Ex
final AddressBook addressBook =
new RandomAddressBookGenerator(r).setSize(numNodes).build();
final NodeId selfId = addressBook.getNodeId(r.nextInt(numNodes));
final StaticTopology topology = new StaticTopology(r, addressBook, selfId, numNeighbors);

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

final StaticConnectionManagers managers = new StaticConnectionManagers(topology, connectionCreator);
final List<NodeId> neighbors = topology.getNeighbors();
final List<NodeId> neighbors = topology.getNeighbors().stream().toList();
final NodeId neighbor = neighbors.get(r.nextInt(neighbors.size()));

if (topology.shouldConnectToMe(neighbor)) {
Expand Down Expand Up @@ -90,9 +96,11 @@ void testShouldConnectTo(final int numNodes, final int numNeighbors) throws Exce
final AddressBook addressBook =
new RandomAddressBookGenerator(r).setSize(numNodes).build();
final NodeId selfId = addressBook.getNodeId(r.nextInt(numNodes));
final StaticTopology topology = new StaticTopology(r, addressBook, selfId, numNeighbors);
final List<PeerInfo> peers = Utilities.createPeerInfoList(addressBook, selfId);
final NetworkTopology topology = new StaticTopology(r, peers, selfId, numNeighbors);

final StaticConnectionManagers managers = new StaticConnectionManagers(topology, connectionCreator);
final List<NodeId> neighbors = topology.getNeighbors();
final List<NodeId> neighbors = topology.getNeighbors().stream().toList();
final NodeId neighbor = neighbors.get(r.nextInt(neighbors.size()));

if (topology.shouldConnectTo(neighbor)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import static org.junit.jupiter.api.Assertions.assertTrue;

import com.swirlds.common.platform.NodeId;
import com.swirlds.platform.Utilities;
import com.swirlds.platform.network.PeerInfo;
import com.swirlds.platform.network.RandomGraph;
import com.swirlds.platform.network.topology.NetworkTopology;
import com.swirlds.platform.network.topology.StaticTopology;
Expand All @@ -34,6 +36,7 @@
import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
Expand Down Expand Up @@ -124,12 +127,15 @@ void testFullyConnectedTopology(final int numNodes, final int numNeighbors, fina
final NodeId outOfBoundsId = addressBook.getNextNodeId();
final NodeId thisNodeId = addressBook.getNodeId(thisNode);
final Random random = getRandomPrintSeed();
final NetworkTopology topology = new StaticTopology(random, addressBook, thisNodeId, numNeighbors);
final List<NodeId> neighbors = topology.getNeighbors();
final List<NodeId> expected = IntStream.range(0, numNodes)

final List<PeerInfo> peers = Utilities.createPeerInfoList(addressBook, thisNodeId);

final NetworkTopology topology = new StaticTopology(random, peers, thisNodeId, numNeighbors);
final Set<NodeId> neighbors = topology.getNeighbors();
final Set<NodeId> expected = IntStream.range(0, numNodes)
.mapToObj(addressBook::getNodeId)
.filter(nodeId -> !Objects.equals(thisNodeId, nodeId))
.toList();
.collect(Collectors.toSet());
assertEquals(expected, neighbors, "all should be neighbors except me");
for (final NodeId neighbor : neighbors) {
assertTrue(
Expand Down
Binary file not shown.
Binary file not shown.