From 254c6d67b2c764fc71916f35d1e67eb941a9013c Mon Sep 17 00:00:00 2001 From: Arunima Chaudhuri Date: Wed, 19 Feb 2025 22:28:23 +0530 Subject: [PATCH] add connect_peers() --- DAS/node.py | 54 ++++++++++++------------------------------------ DAS/shape.py | 4 +++- DAS/simulator.py | 22 ++++++++++++++++++++ smallConf.py | 24 +++++++++++++++++---- study.py | 1 + 5 files changed, 59 insertions(+), 46 deletions(-) diff --git a/DAS/node.py b/DAS/node.py index 15d29bd..93ade54 100644 --- a/DAS/node.py +++ b/DAS/node.py @@ -81,13 +81,14 @@ class Node: self.logger = logger self.validators = validators self.received_gossip = defaultdict(list) + self.peer_connections = set() # query methods - self.exponential_growth = True + self.exponential_growth = False self.linear_growth = False self.linear_constant_growth = False self.hybrid_growth = False - self.exponential_constant_growth = False + self.exponential_constant_growth = True self.linear_growth_constant = 10 # query results @@ -722,57 +723,28 @@ class Node: query_times.append(0) all_original_retries.append(0) else: - row_neighbors_copy = {row: list(neighbors) for row, neighbors in self.rowNeighbors.items()} - column_neighbors_copy = {col: list(neighbors) for col, neighbors in self.columnNeighbors.items()} - - row_peer_ids = list({node_id for neighbors in row_neighbors_copy.values() for node_id in neighbors}) - col_peer_ids = list({node_id for neighbors in column_neighbors_copy.values() for node_id in neighbors}) - + peers_with_custody = set() - for peer_id in row_peer_ids: + for peer_id in self.peer_connections: if (sample_row in simulator.validators[peer_id].rowIDs or sample_col in simulator.validators[peer_id].columnIDs or len(simulator.validators[peer_id].rowIDs) >= self.shape.nbRowsK or len(simulator.validators[peer_id].columnIDs) >= self.shape.nbColsK): peers_with_custody.update({peer_id}) - for peer_id in col_peer_ids: - if (sample_row in simulator.validators[peer_id].rowIDs or - sample_col in simulator.validators[peer_id].columnIDs or - len(simulator.validators[peer_id].rowIDs) >= self.shape.nbRowsK or - len(simulator.validators[peer_id].columnIDs) >= self.shape.nbColsK): - peers_with_custody.update({peer_id}) - peers_with_custody = list(peers_with_custody) - peers_with_custody_level_2 = [] - - row_neighbors_l2 = set() - col_neighbors_l2 = set() - - for p in row_peer_ids: - for neighbors in simulator.validators[p].rowNeighbors.values(): - row_neighbors_l2.update(neighbors) - for neighbors in simulator.validators[p].columnNeighbors.values(): - row_neighbors_l2.update(neighbors) - - for p in col_peer_ids: - for neighbors in simulator.validators[p].rowNeighbors.values(): - col_neighbors_l2.update(neighbors) - for neighbors in simulator.validators[p].columnNeighbors.values(): - col_neighbors_l2.update(neighbors) - - - neighbors_level_2 = list(row_neighbors_l2.union(col_neighbors_l2)) peers_with_custody_level_2 = set() - for p in neighbors_level_2: - if (sample_row in simulator.validators[p].rowIDs or - sample_col in simulator.validators[p].columnIDs or - len(simulator.validators[p].rowIDs) >= self.shape.nbRowsK or - len(simulator.validators[p].columnIDs) >= self.shape.nbColsK): - peers_with_custody_level_2.update({p}) + for p in self.peer_connections: + for peer_l2 in simulator.validators[p].peer_connections: + if (sample_row in simulator.validators[peer_l2].rowIDs or + sample_col in simulator.validators[peer_l2].rowIDs or + len(simulator.validators[peer_l2].rowIDs) >= self.shape.nbRowsK or + len(simulator.validators[peer_l2].columnIDs) >= self.shape.nbColsK): + peers_with_custody_level_2.update({peer_l2}) + peers_with_custody_level_2 = list(peers_with_custody_level_2) if self.ID in peers_with_custody: diff --git a/DAS/shape.py b/DAS/shape.py index f559176..49646ff 100644 --- a/DAS/shape.py +++ b/DAS/shape.py @@ -3,7 +3,7 @@ class Shape: """This class represents a set of parameters for a specific simulation.""" def __init__(self, nbCols, nbColsK, nbRows, nbRowsK, - numberNodes, failureModel, failureRate, maliciousNodes, custodyRows, custodyCols, minCustodyRows, minCustodyCols, netDegree, bwUplinkProd, run, nodeTypes): + numberNodes, failureModel, failureRate, maliciousNodes, custodyRows, custodyCols, minCustodyRows, minCustodyCols, netDegree, numPeersMin, numPeersMax, bwUplinkProd, run, nodeTypes): """Initializes the shape with the parameters passed in argument.""" self.run = run self.numberNodes = numberNodes @@ -15,6 +15,7 @@ class Shape: self.failureRate = failureRate self.maliciousNodes = maliciousNodes self.netDegree = netDegree + self.numPeers = [numPeersMin, numPeersMax] self.custodyRows = custodyRows self.custodyCols = custodyCols self.minCustodyRows = minCustodyRows @@ -43,6 +44,7 @@ class Shape: shastr += "-r-"+str(self.run) shastr += "-mn-"+str(self.maliciousNodes) shastr += "-ntypes-"+str(self.nodeTypes['group']) + shastr += "-np-"+str(self.numPeers) return shastr def setSeed(self, seed): diff --git a/DAS/simulator.py b/DAS/simulator.py index 0db8cbd..0d940dc 100644 --- a/DAS/simulator.py +++ b/DAS/simulator.py @@ -236,6 +236,27 @@ class Simulator: self.logger.debug("Val %d : rowN %s", i, self.validators[i].rowNeighbors, extra=self.format) self.logger.debug("Val %d : colN %s", i, self.validators[i].columnNeighbors, extra=self.format) + def connect_peers(self): + connections_range = self.shape.numPeers + + for peer in self.validators: + num_connections = random.randint(connections_range[0], connections_range[1]) + available_peers = [i for i in range(self.shape.numberNodes)] + + for neighbor_dict in [peer.rowNeighbors, peer.columnNeighbors]: + for inner_dict in neighbor_dict.values(): + for peers in inner_dict.values(): + peer.peer_connections.add(peers.node.ID) + + available_peers = list(set(available_peers) - peer.peer_connections) + random.shuffle(available_peers) + + while len(peer.peer_connections) < num_connections and available_peers: + other_peer = available_peers.pop() + if other_peer != peer.ID and len(self.validators[other_peer].peer_connections) < num_connections: + peer.peer_connections.add(other_peer) + self.validators[other_peer].peer_connections.add(peer.ID) + def initLogger(self): """It initializes the logger.""" logging.TRACE = 5 @@ -429,4 +450,5 @@ class Simulator: self.result.addMetric("progress", progress.to_dict(orient='list')) self.result.populate(self.shape, self.config, missingVector) self.result.copyValidators(self.validators) + print(self.validators[1].statsTxPerSlot) return self.result diff --git a/smallConf.py b/smallConf.py index 0b531c5..4188ed4 100644 --- a/smallConf.py +++ b/smallConf.py @@ -68,6 +68,9 @@ heartbeat = 20 # Per-topic mesh neighborhood size netDegrees = range(8, 9, 2) +# Number of peers for sampling +numPeers = [[50, 150]] + # How many copies are sent out by the block producer # Note, previously this was set to match netDegree proposerPublishToR = "shape.netDegree" @@ -169,19 +172,32 @@ def nextShape(): "minCustodyCols": minCustodyCols, "numberNodes": numberNodes, "netDegrees": netDegrees, + "numPeers": numPeers, "bwUplinksProd": bwUplinksProd, "nodeTypesGroup": nodeTypesGroup, } + for key, value in params.items(): if not value: logging.warning(f"The parameter '{key}' is empty. Please assign a value and start the simulation.") exit(1) - for nbCols, nbColsK, nbRows, nbRowsK, run, fm, fr, mn, chR, chC, minChR, minChC, nn, netDegree, bwUplinkProd, nodeTypes in itertools.product( - cols, colsK, rows, rowsK, runs, failureModels, failureRates, maliciousNodes, custodyRows, custodyCols, minCustodyRows, minCustodyCols, numberNodes, netDegrees, bwUplinksProd, nodeTypesGroup): - # Network Degree has to be an even number + for ( + nbCols, nbColsK, nbRows, nbRowsK, run, fm, fr, mn, chR, chC, minChR, minChC, + nn, netDegree, numPeersList, bwUplinkProd, nodeTypes + ) in itertools.product( + cols, colsK, rows, rowsK, runs, failureModels, failureRates, maliciousNodes, + custodyRows, custodyCols, minCustodyRows, minCustodyCols, numberNodes, + netDegrees, numPeers, bwUplinksProd, nodeTypesGroup + ): + numPeersMin, numPeersMax = numPeersList # Unpack here + + # Ensure netDegree is even if netDegree % 2 == 0: - shape = Shape(nbCols, nbColsK, nbRows, nbRowsK, nn, fm, fr, mn, chR, chC, minChR, minChC, netDegree, bwUplinkProd, run, nodeTypes) + shape = Shape( + nbCols, nbColsK, nbRows, nbRowsK, nn, fm, fr, mn, chR, chC, minChR, + minChC, netDegree, numPeersMin, numPeersMax, bwUplinkProd, run, nodeTypes + ) yield shape def evalConf(self, param, shape = None): diff --git a/study.py b/study.py index 0e47a77..52d9908 100644 --- a/study.py +++ b/study.py @@ -43,6 +43,7 @@ def runOnce(config, shape, execID): sim.initLogger() sim.initValidators() sim.initNetwork() + sim.connect_peers() result = sim.run() sim.logger.info("Shape: %s ... Block Available: %d in %d steps" % (str(sim.shape.__dict__), result.blockAvailable, len(result.missingVector)), extra=sim.format)