Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
5d09eb9
prueba
isaac1227 Nov 13, 2024
c30e1df
solved when the scenario stops because some nodes go faster than others
isaac1227 Nov 22, 2024
767954b
add in frontend new attack at select
isaac1227 Dec 3, 2024
3013935
implemented attack flood
isaac1227 Dec 3, 2024
7a1f095
changes in metrics
isaac1227 Dec 3, 2024
08c43db
changes to implemented flooding attack
isaac1227 Dec 3, 2024
745e074
changes metric flooding
isaac1227 Dec 5, 2024
6df3b4d
changes in .gitignore
isaac1227 Dec 5, 2024
600c5b5
changes of the week
isaac1227 Dec 13, 2024
393bb0c
changes to improve metrics fraction of changed parameters
isaac1227 Dec 16, 2024
f1c737b
Merge remote-tracking branch 'origin/main' into feat_reputation
isaac1227 Dec 16, 2024
24534e5
changes metrics
isaac1227 Jan 7, 2025
59ffc17
changes in history_reputation
isaac1227 Jan 7, 2025
0166f53
changes at metric model_latency_arrival
isaac1227 Jan 10, 2025
f9cef06
implemented dynamic score
isaac1227 Jan 16, 2025
06e9600
Merge branch 'main' into feat_reputation
isaac1227 Jan 16, 2025
e6e1c58
reputational adjustments
isaac1227 Jan 20, 2025
81a8824
update config and dynamic reputation
isaac1227 Jan 28, 2025
ee1ebd0
merge with main and reputation to incorporate attacks
isaac1227 Jan 28, 2025
5503d3b
small adjustments after including the attacks of main branch
isaac1227 Jan 28, 2025
7d234c8
return None when ignored model for the aggregation
isaac1227 Jan 30, 2025
f4bc554
float metrics similarity, quit reputation of malicious node, add floo…
isaac1227 Feb 24, 2025
b910e77
Merge remote-tracking branch 'origin/main' into feat_rep_main
isaac1227 Feb 24, 2025
25d79b1
add reputation message to new message optimization
isaac1227 Feb 28, 2025
4d11775
add reputation message to new message optimization
isaac1227 Feb 28, 2025
4336070
Merge branch 'main' into feat_reputation
isaac1227 Mar 11, 2025
6f1d0dd
Merge remote-tracking branch 'origin/main' into feat_reputation
isaac1227 Mar 11, 2025
2602fb2
changes to make everything work correctly after the merge with the ma…
isaac1227 Mar 12, 2025
220d849
new configuration at front and changes in back to dynamic and static …
isaac1227 Mar 20, 2025
8906664
all functions within the reputation module, event management
isaac1227 Mar 24, 2025
69f1d90
Merge remote-tracking branch 'origin/main' into feat_reputation
isaac1227 Mar 24, 2025
81161a6
update the deployent.html file
isaac1227 Mar 24, 2025
ed35623
update function get_round_updates()
isaac1227 Mar 25, 2025
580cc0a
fix flooding
isaac1227 Mar 25, 2025
e07b6ab
fix reputation
isaac1227 Mar 26, 2025
59d5c88
changes metric value
isaac1227 Mar 26, 2025
94e4d0b
changes to better finally metric value
isaac1227 Mar 26, 2025
1d5357f
Improve efficiency and clean up redundant code
FerTV Mar 26, 2025
9d5b7b8
fix launching scenarios without reputation
FerTV Mar 27, 2025
8dc4a13
Improved metric calculations in the reputation module for greater acc…
isaac1227 Mar 27, 2025
d61f7da
move reputation.py to addons and remove JSON from metrics
isaac1227 Mar 28, 2025
9980553
Refactor: Scale model weights based on node reputation, optimize metr…
isaac1227 Apr 9, 2025
45cfc73
Refactor model aggregation to reject models not from the current roun…
isaac1227 Apr 9, 2025
8206d52
Merge remote-tracking branch 'origin/main' into feat_reputation
isaac1227 Apr 9, 2025
2fa7c54
Merge remote-tracking branch 'origin/main' into feat_reputation
isaac1227 Apr 29, 2025
905748b
Enhance robustness of reputation metrics against intermittent delay a…
isaac1227 May 8, 2025
eb917d5
last changes - reputation calculated from round 1
isaac1227 May 20, 2025
081c2d0
Merge remote-tracking branch 'origin/main' into feat_reputation
isaac1227 May 20, 2025
d5bba4a
feat: adapt frontend and backend to enable reputation after config re…
isaac1227 May 20, 2025
a847a1a
Merge remote-tracking branch 'origin/main' into feat_reputation
isaac1227 Jun 2, 2025
65ee7ae
improve naming between frontend/controller
isaac1227 Jun 2, 2025
bbceece
resolve merge conflicts with main
isaac1227 Jun 10, 2025
e124509
Merge remote-tracking branch 'origin/main' into feat_reputation
isaac1227 Jun 10, 2025
4ee5e1a
Created the DuplicatedMessageEvent to capture and manage duplicated (…
isaac1227 Jun 11, 2025
f91fa40
Refactored: the reputation system is now part of the defense module f…
isaac1227 Jun 11, 2025
9d310c7
Merge remote-tracking branch 'origin/main' into feat_reputation
isaac1227 Jun 11, 2025
342ff50
Merge remote-tracking branch 'origin/main' into feat_reputation
isaac1227 Jun 17, 2025
9cfceeb
Merge remote-tracking branch 'origin/main' into feat_reputation
isaac1227 Jun 17, 2025
0657c93
Merge remote-tracking branch 'origin/main' into feat_reputation
isaac1227 Jun 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file modified CHANGELOG.md
100644 → 100755
Empty file.
Empty file modified CONTRIBUTING.md
100644 → 100755
Empty file.
Empty file modified Makefile
100644 → 100755
Empty file.
Empty file modified docs/_prebuilt/changelog.md
100644 → 100755
Empty file.
Empty file modified docs/_prebuilt/contributing.md
100644 → 100755
Empty file.
Empty file modified docs/_prebuilt/css/toc.css
100644 → 100755
Empty file.
Empty file modified docs/_prebuilt/developerguide.md
100644 → 100755
Empty file.
Empty file modified docs/_prebuilt/index.md
100644 → 100755
Empty file.
Empty file modified docs/_prebuilt/installation.md
100644 → 100755
Empty file.
Empty file modified docs/_prebuilt/js/toc.js
100644 → 100755
Empty file.
Empty file modified docs/_prebuilt/static/developerguide/structure.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified docs/_prebuilt/static/userguide/deployment.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified docs/_prebuilt/static/userguide/frontend.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified docs/_prebuilt/static/userguide/monitor.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified docs/_prebuilt/static/userguide/nebula-dashboard.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified docs/_prebuilt/static/userguide/realtime-images.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified docs/_prebuilt/static/userguide/realtime-scalars.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified docs/_prebuilt/static/userguide/realtime-time-series.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified docs/_prebuilt/static/userguide/running_nebula.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified docs/_prebuilt/userguide.md
100644 → 100755
Empty file.
Empty file modified docs/mkdocs.yml
100644 → 100755
Empty file.
Empty file modified docs/scripts/gen_ref_pages.py
100644 → 100755
Empty file.
Empty file modified nebula/addons/attacks/communications/__init__.py
100644 → 100755
Empty file.
Empty file modified nebula/addons/attacks/communications/communicationattack.py
100644 → 100755
Empty file.
Empty file modified nebula/addons/attacks/communications/delayerattack.py
100644 → 100755
Empty file.
11 changes: 7 additions & 4 deletions nebula/addons/attacks/communications/floodingattack.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ def decorator(self, flooding_factor: int):
def decorator(func):
@wraps(func)
async def wrapper(*args, **kwargs):
if len(args) == 4 and args[3] == "model":
flooding_factor = 30

Copilot AI Jun 23, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line overwrites the outer flooding_factor parameter with a hard-coded 30, ignoring the configured value. Remove this override or use the passed-in factor.

Suggested change
flooding_factor = 30
# Use the passed-in flooding_factor parameter

Copilot uses AI. Check for mistakes.
if len(args) > 1:
dest_addr = args[1]
if dest_addr in self.targets:
logging.info(f"[FloodingAttack] Flooding message to {dest_addr} by {flooding_factor} times")
Expand All @@ -67,11 +68,13 @@ async def wrapper(*args, **kwargs):
logging.info(
f"[FloodingAttack] Sending duplicate {i + 1}/{flooding_factor} to {dest_addr}"
)
_, *new_args = args # Exclude self argument
_, dest_addr, serialized_model, *rest = args # Exclude self argument
new_args = [dest_addr, serialized_model]
await func(*new_args, **kwargs)
_, *new_args = args
_, dest_addr, serialized_model, *rest = args # Exclude self argument
new_args = [dest_addr, serialized_model]
return await func(*new_args)

return wrapper

return decorator
Empty file modified nebula/addons/attacks/dataset/datasetattack.py
100644 → 100755
Empty file.
Empty file modified nebula/addons/attacks/model/gllneuroninversion.py
100644 → 100755
Empty file.
Empty file modified nebula/addons/attacks/model/modelattack.py
100644 → 100755
Empty file.
Empty file modified nebula/addons/attacks/model/swappingweights.py
100644 → 100755
Empty file.
Empty file modified nebula/addons/gps/gpsmodule.py
100644 → 100755
Empty file.
Empty file modified nebula/addons/gps/nebulagps.py
100644 → 100755
Empty file.
Empty file modified nebula/addons/networksimulation/nebulanetworksimulator.py
100644 → 100755
Empty file.
Empty file modified nebula/addons/networksimulation/networksimulator.py
100644 → 100755
Empty file.
1,281 changes: 705 additions & 576 deletions nebula/addons/reputation/reputation.py
100644 → 100755

Large diffs are not rendered by default.

25 changes: 22 additions & 3 deletions nebula/controller/scenarios.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ def validate_positive_int(value, name):
"Flooding",
}


# Get attack type from attack_params
if attack_params and "attacks" in attack_params:
attack = attack_params["attacks"]
Expand Down Expand Up @@ -544,7 +545,7 @@ def from_dict(cls, data):

# Create the scenario object
scenario = cls(**scenario_data)

return scenario


Expand Down Expand Up @@ -697,8 +698,26 @@ def __init__(self, scenario, user=None):
participant_config["adversarial_args"]["attack_params"] = node_config["attack_params"]
else:
participant_config["adversarial_args"]["attack_params"] = {"attacks": "No Attack"}
participant_config["defense_args"]["reputation"] = self.scenario.reputation

# Defense parameters

Copilot AI Jun 23, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

participant_config["defense_args"]["reputation"] is never initialized before assigning nested keys, which will raise a KeyError. Ensure reputation is initialized as an object before setting its fields.

Suggested change
# Defense parameters
# Defense parameters
participant_config["defense_args"].setdefault("reputation", {})

Copilot uses AI. Check for mistakes.
participant_config["defense_args"]["reputation"]["with_reputation"] = self.scenario.reputation.get("with_reputation", False)
participant_config["defense_args"]["reputation"]["initial_reputation"] = self.scenario.reputation.get("initial_reputation", 0.2)
metrics_list = self.scenario.reputation.get("reputation_metrics", [])
if isinstance(metrics_list, list):
metrics_dict = {
"model_similarity": "model_similarity" in metrics_list,
"num_messages": "num_messages" in metrics_list,
"model_arrival_latency": "model_arrival_latency" in metrics_list,
"fraction_parameters_changed": "fraction_parameters_changed" in metrics_list,
}
participant_config["defense_args"]["reputation"]["reputation_metrics"] = metrics_dict
else:
participant_config["defense_args"]["reputation"]["reputation_metrics"] = metrics_list
participant_config["defense_args"]["reputation"]["weighting_factor"] = self.scenario.reputation.get("weighting_factor", "dynamic")
participant_config["defense_args"]["reputation"]["weight_model_arrival_latency"] = self.scenario.reputation.get("weight_model_arrival_latency", 1.0)
participant_config["defense_args"]["reputation"]["weight_model_similarity"] = self.scenario.reputation.get("weight_model_similarity", 1.0)
participant_config["defense_args"]["reputation"]["weight_num_messages"] = self.scenario.reputation.get("weight_num_messages", 1.0)
participant_config["defense_args"]["reputation"]["weight_fraction_params_changed"] = self.scenario.reputation.get("weight_fraction_params_changed", 1.0)
# Mobility and network simulation parameters
participant_config["mobility_args"]["random_geo"] = self.scenario.random_geo
participant_config["mobility_args"]["latitude"] = self.scenario.latitude
participant_config["mobility_args"]["longitude"] = self.scenario.longitude
Expand Down
Empty file modified nebula/core/addonmanager.py
100644 → 100755
Empty file.
Empty file modified nebula/core/aggregation/updatehandlers/cflupdatehandler.py
100644 → 100755
Empty file.
6 changes: 4 additions & 2 deletions nebula/core/aggregation/updatehandlers/dflupdatehandler.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ async def _check_updates_already_received(self):
logging.info(
f"Update already received from source: {se} | ({len(self._sources_received)}/{len(self._sources_expected)}) Updates received"
)
logging.info(
f"Update already received from source: {se} | ({len(self._sources_received)}/{len(self._sources_expected)}) Updates received"
)
Comment on lines +140 to +142

Copilot AI Jun 23, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] This logging statement is duplicated immediately before; consider removing one to avoid redundant output.

Suggested change
logging.info(
f"Update already received from source: {se} | ({len(self._sources_received)}/{len(self._sources_expected)}) Updates received"
)

Copilot uses AI. Check for mistakes.
except:
logging.exception(
f"ERROR: source expected: {se} | last_update None: {(True if not last_updt else False)}, last update storaged None: {(True if not node_storage[-1] else False)}"
Expand All @@ -163,8 +166,8 @@ async def storage_update(self, updt_received_event: UpdateReceivedEvent):
logging.info(
f"Storage Update | source={source} | round={round} | weight={weight} | federation nodes: {self._sources_expected}"
)

self._sources_received.add(source)

updates_left = self._sources_expected.difference(self._sources_received)
logging.info(
f"Updates received ({len(self._sources_received)}/{len(self._sources_expected)}) | Missing nodes: {updates_left}"
Expand Down Expand Up @@ -192,7 +195,6 @@ async def get_round_updates(self):
logging.info(f"Missing updates from sources: {updates_missing}")
else:
self._missing_ones.clear()

self._nodes_using_historic.clear()
updates = {}
for sr in self._sources_received:
Expand Down
Empty file modified nebula/core/aggregation/updatehandlers/sdflupdatehandler.py
100644 → 100755
Empty file.
Empty file modified nebula/core/aggregation/updatehandlers/updatehandler.py
100644 → 100755
Empty file.
25 changes: 23 additions & 2 deletions nebula/core/engine.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ def __init__(
else:
self._situational_awareness = None

if self.config.participant["defense_args"]["reputation"]["enabled"]:
if self.config.participant["defense_args"]["reputation"]["with_reputation"]:
self._reputation = Reputation(engine=self, config=self.config)

@property
Expand Down Expand Up @@ -354,6 +354,27 @@ async def _federation_federation_start_callback(self, source, message):
logging.info(f"📝 handle_federation_message | Trigger | Received start federation message from {source}")
await self.create_trainer_module()

async def _reputation_share_callback(self, source, message):
try:
logging.info(f"handle_reputation_message | Trigger | Received reputation message from {source} | Node: {message.node_id} | Score: {message.score} | Round: {message.round}")

current_node = self.addr
nei = message.node_id

if hasattr(self, '_reputation') and self._reputation is not None:
if current_node != nei:
key = (current_node, nei, message.round)

if key not in self._reputation.reputation_with_all_feedback:
self._reputation.reputation_with_all_feedback[key] = []

self._reputation.reputation_with_all_feedback[key].append(message.score)
else:
logging.error("Reputation object (_reputation) is not available.")

except Exception as e:
logging.exception(f"Error handling reputation message: {e}")

async def _federation_federation_models_included_callback(self, source, message):
logging.info(f"📝 handle_federation_message | Trigger | Received aggregation finished message from {source}")

Expand Down Expand Up @@ -591,7 +612,7 @@ async def deploy_components(self):
await self.aggregator.init()
if "situational_awareness" in self.config.participant:
await self.sa.init()
if self.config.participant["defense_args"]["reputation"]["enabled"]:
if self.config.participant["defense_args"]["reputation"]["with_reputation"]:
await self._reputation.setup()
await self._reporter.start()
await self._addon_manager.deploy_additional_services()
Expand Down
20 changes: 20 additions & 0 deletions nebula/core/nebulaevents.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,26 @@ async def get_event_data(self) -> tuple[str, tuple[float, float]]:

async def is_concurrent(self) -> bool:
return True

class DuplicatedMessageEvent(NodeEvent):
"""
Event triggered when a message is received that has already been processed.

Attributes:
source (str): The address of the node that sent the duplicated message.
"""

def __init__(self, source: str, message_type: str):
self.source = source

def __str__(self):
return f"DuplicatedMessageEvent from {self.source}"

async def get_event_data(self) -> tuple[str]:
return (self.source)

Comment on lines +346 to +353

Copilot AI Jun 23, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DuplicatedMessageEvent.__init__ accepts message_type but does not assign it or call the base NodeEvent constructor, and get_event_data returns a plain string instead of a tuple. Initialize all attributes and invoke super().__init__ if needed, and return a proper tuple.

Suggested change
self.source = source
def __str__(self):
return f"DuplicatedMessageEvent from {self.source}"
async def get_event_data(self) -> tuple[str]:
return (self.source)
super().__init__() # Ensure proper initialization of the base class
self.source = source
self.message_type = message_type
def __str__(self):
return f"DuplicatedMessageEvent from {self.source}, type: {self.message_type}"
async def get_event_data(self) -> tuple[str, str]:
"""
Retrieves the event data.
Returns:
tuple[str, str]: A tuple containing:
- The source of the duplicated message.
- The type of the duplicated message.
"""
return (self.source, self.message_type)

Copilot uses AI. Check for mistakes.
async def is_concurrent(self) -> bool:
return True


""" ##############################
Expand Down
Empty file modified nebula/core/network/actions.py
100644 → 100755
Empty file.
Empty file modified nebula/core/network/blacklist.py
100644 → 100755
Empty file.
6 changes: 4 additions & 2 deletions nebula/core/network/communications.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import requests

from nebula.core.eventmanager import EventManager
from nebula.core.nebulaevents import MessageEvent
from nebula.core.nebulaevents import MessageEvent, DuplicatedMessageEvent
from nebula.core.network.blacklist import BlackList
from nebula.core.network.connection import Connection
from nebula.core.network.discoverer import Discoverer
Expand Down Expand Up @@ -803,7 +803,7 @@ async def deploy_additional_services(self):
await self._forwarder.start()
self._propagator.start()

async def include_received_message_hash(self, hash_message):
async def include_received_message_hash(self, hash_message, source=None):
"""
Adds a received message hash to the tracking list if it hasn't been seen before.

Expand All @@ -819,6 +819,8 @@ async def include_received_message_hash(self, hash_message):
await self.receive_messages_lock.acquire_async()
if hash_message in self.received_messages_hashes:
logging.info("❗️ handle_incoming_message | Ignoring message already received.")
duplicated_event = DuplicatedMessageEvent(source, "Duplicated message received")
asyncio.create_task(EventManager.get_instance().publish_node_event(duplicated_event))
return False
self.received_messages_hashes.append(hash_message)
if len(self.received_messages_hashes) % 10000 == 0:
Expand Down
Empty file.
Empty file.
2 changes: 1 addition & 1 deletion nebula/core/network/messages.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ async def process_message(self, data, addr_from):

# Message-specific forwarding and processing
elif message_type in special_processing_messages:
if await self.cm.include_received_message_hash(hashlib.md5(data).hexdigest()):
if await self.cm.include_received_message_hash(hashlib.md5(data).hexdigest(), addr_from):
# Forward the message if required
if self._should_forward_message(message_type, message_wrapper):
await self.cm.forward_message(data, addr_from)
Expand Down
Empty file modified nebula/core/pb/nebula_pb2.py
100644 → 100755
Empty file.
Empty file modified nebula/core/situationalawareness/__init__.py
100644 → 100755
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file modified nebula/core/situationalawareness/awareness/sareasoner.py
100644 → 100755
Empty file.
Empty file modified nebula/core/situationalawareness/awareness/sautils/sacommand.py
100644 → 100755
Empty file.
Empty file.
Empty file.
Empty file modified nebula/core/situationalawareness/awareness/suggestionbuffer.py
100644 → 100755
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file modified nebula/core/situationalawareness/situationalawareness.py
100644 → 100755
Empty file.
Empty file modified nebula/core/utils/tasks.py
100644 → 100755
Empty file.
6 changes: 3 additions & 3 deletions nebula/frontend/config/participant.json.example
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@
},
"defense_args": {
"reputation": {
"enabled": false,
"metrics": {},
"initial_reputation": 0.6,
"with_reputation": false,
"reputation_metrics": [],
"initial_reputation": 0.2,
"weighting_factor": "dynamic"
}
},
Expand Down
Empty file modified nebula/frontend/static/css/dashboard.css
100644 → 100755
Empty file.
Empty file modified nebula/frontend/static/css/deployment.css
100644 → 100755
Empty file.
Empty file modified nebula/frontend/static/css/particles.css
100644 → 100755
Empty file.
Empty file modified nebula/frontend/static/images/physical-device.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified nebula/frontend/static/js/dashboard/config-manager.js
100644 → 100755
Empty file.
Empty file modified nebula/frontend/static/js/dashboard/dashboard.js
100644 → 100755
Empty file.
Empty file modified nebula/frontend/static/js/dashboard/notes-manager.js
100644 → 100755
Empty file.
Empty file modified nebula/frontend/static/js/dashboard/scenario-actions.js
100644 → 100755
Empty file.
Empty file modified nebula/frontend/static/js/deployment/attack.js
100644 → 100755
Empty file.
Empty file modified nebula/frontend/static/js/deployment/graph-settings.js
100644 → 100755
Empty file.
Empty file modified nebula/frontend/static/js/deployment/help-content.js
100644 → 100755
Empty file.
Empty file modified nebula/frontend/static/js/deployment/main.js
100644 → 100755
Empty file.
Empty file modified nebula/frontend/static/js/deployment/mobility.js
100644 → 100755
Empty file.
88 changes: 40 additions & 48 deletions nebula/frontend/static/js/deployment/reputation.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -60,70 +60,62 @@ const ReputationManager = (function() {
}

function getReputationConfig() {
const rep_metrics = [];

if (document.getElementById("model-similarity").checked)
rep_metrics.push("model_similarity");
if (document.getElementById("num-messages").checked)
rep_metrics.push("num_messages");
if (document.getElementById("model-arrival-latency").checked)
rep_metrics.push("model_arrival_latency");
if (document.getElementById("fraction-parameters-changed").checked)
rep_metrics.push("fraction_parameters_changed");

return {
enabled: document.getElementById("reputationSwitch").checked,
initialReputation: parseFloat(document.getElementById("initial-reputation").value),
weightingFactor: document.getElementById("weighting-factor").value,
metrics: {
model_similarity: {
enabled: document.getElementById("model-similarity").checked,
weight: parseFloat(document.getElementById("weight-model-similarity").value)
},
num_messages: {
enabled: document.getElementById("num-messages").checked,
weight: parseFloat(document.getElementById("weight-num-messages").value)
},
model_arrival_latency: {
enabled: document.getElementById("model-arrival-latency").checked,
weight: parseFloat(document.getElementById("weight-model-arrival-latency").value)
},
fraction_parameters_changed: {
enabled: document.getElementById("fraction-parameters-changed").checked,
weight: parseFloat(document.getElementById("weight-fraction-parameters-changed").value)
}
}
with_reputation: document.getElementById("reputationSwitch").checked,
reputation_metrics: rep_metrics,
initial_reputation: parseFloat(document.getElementById("initial-reputation").value),
weighting_factor: document.getElementById("weighting-factor").value,
weight_model_arrival_latency: parseFloat(document.getElementById("weight-model-arrival-latency").value),
weight_model_similarity: parseFloat(document.getElementById("weight-model-similarity").value),
weight_num_messages: parseFloat(document.getElementById("weight-num-messages").value),
weight_fraction_params_changed: parseFloat(document.getElementById("weight-fraction-parameters-changed").value),
};
}

function setReputationConfig(config) {
if (!config) return;

// Set reputation enabled/disabled
document.getElementById("reputationSwitch").checked = config.enabled;
document.getElementById("reputation-metrics").style.display = config.enabled ? "block" : "none";
document.getElementById("reputation-settings").style.display = config.enabled ? "block" : "none";
document.getElementById("weighting-settings").style.display = config.enabled ? "block" : "none";
const enabled = config.with_reputation ?? config.enabled ?? false;

// Set reputation switch and visibility
document.getElementById("reputationSwitch").checked = enabled;
document.getElementById("reputation-metrics").style.display = enabled ? "block" : "none";
document.getElementById("reputation-settings").style.display = enabled ? "block" : "none";
document.getElementById("weighting-settings").style.display = enabled ? "block" : "none";

// Set initial reputation
document.getElementById("initial-reputation").value = config.initialReputation || 0.6;
// Initial reputation and weighting factor
document.getElementById("initial-reputation").value = config.initial_reputation ?? config.initialReputation ?? 0.2;
document.getElementById("weighting-factor").value = config.weighting_factor ?? config.weightingFactor ?? "dynamic";

// Set weighting factor
document.getElementById("weighting-factor").value = config.weightingFactor || "dynamic";
const showWeights = config.weightingFactor === "static";
const showWeights = (config.weighting_factor ?? config.weightingFactor) === "static";
document.querySelectorAll(".weight-input").forEach(input => {
input.style.display = showWeights ? "inline-block" : "none";
});

// Set metrics
if (config.metrics) {
// Model Similarity
document.getElementById("model-similarity").checked = config.metrics.modelSimilarity?.enabled || false;
document.getElementById("weight-model-similarity").value = config.metrics.modelSimilarity?.weight || 0;
// Metrics (both legacy flat and nested)
document.getElementById("model-similarity").checked = config.reputation_metrics?.includes("modelSimilarity") ?? config.metrics?.modelSimilarity?.enabled ?? false;

Copilot AI Jun 23, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The string names in reputation_metrics (snake_case) do not match the camelCase keys checked here (e.g., "modelSimilarity"), so metric toggles will never restore correctly. Align naming or normalize both sides.

Copilot uses AI. Check for mistakes.
document.getElementById("weight-model-similarity").value = config.weight_model_similarity ?? config.metrics?.modelSimilarity?.weight ?? 0;

// Number of Messages
document.getElementById("num-messages").checked = config.metrics.numMessages?.enabled || false;
document.getElementById("weight-num-messages").value = config.metrics.numMessages?.weight || 0;
document.getElementById("num-messages").checked = config.reputation_metrics?.includes("numMessages") ?? config.metrics?.numMessages?.enabled ?? false;
document.getElementById("weight-num-messages").value = config.weight_num_messages ?? config.metrics?.numMessages?.weight ?? 0;

// Model Arrival Latency
document.getElementById("model-arrival-latency").checked = config.metrics.modelArrivalLatency?.enabled || false;
document.getElementById("weight-model-arrival-latency").value = config.metrics.modelArrivalLatency?.weight || 0;
document.getElementById("model-arrival-latency").checked = config.reputation_metrics?.includes("modelArrivalLatency") ?? config.metrics?.modelArrivalLatency?.enabled ?? false;
document.getElementById("weight-model-arrival-latency").value = config.weight_model_arrival_latency ?? config.metrics?.modelArrivalLatency?.weight ?? 0;

// Fraction Parameters Changed
document.getElementById("fraction-parameters-changed").checked = config.metrics.fractionParametersChanged?.enabled || false;
document.getElementById("weight-fraction-parameters-changed").value = config.metrics.fractionParametersChanged?.weight || 0;
}
document.getElementById("fraction-parameters-changed").checked = config.reputation_metrics?.includes("fractionParametersChanged") ?? config.metrics?.fractionParametersChanged?.enabled ?? false;
document.getElementById("weight-fraction-parameters-changed").value = config.weight_fraction_params_changed ?? config.metrics?.fractionParametersChanged?.weight ?? 0;

// Validate weights
validateWeights();
}

Expand All @@ -133,7 +125,7 @@ const ReputationManager = (function() {
document.getElementById("reputation-metrics").style.display = "none";
document.getElementById("reputation-settings").style.display = "none";
document.getElementById("weighting-settings").style.display = "none";
document.getElementById("initial-reputation").value = "0.6";
document.getElementById("initial-reputation").value = "0.2";
document.getElementById("weighting-factor").value = "dynamic";
document.getElementById("weight-warning").style.display = "none";

Expand Down
7 changes: 1 addition & 6 deletions nebula/frontend/static/js/deployment/scenario.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,7 @@ const ScenarioManager = (function() {
report_status_data_queue: document.getElementById("reportingSwitch").checked,
epochs: parseInt(document.getElementById("epochs").value),
attack_params: attackConfig,
reputation: {
enabled: window.ReputationManager.getReputationConfig().enabled || false,
metrics: window.ReputationManager.getReputationConfig().metrics || {},
initial_reputation: window.ReputationManager.getReputationConfig().initialReputation || 0.6,
weighting_factor: window.ReputationManager.getReputationConfig().weightingFactor || "dynamic"
},
reputation: window.ReputationManager.getReputationConfig(),
mobility: window.MobilityManager.getMobilityConfig().enabled || false,
network_simulation: window.MobilityManager.getMobilityConfig().network_simulation || false,
mobility_type: window.MobilityManager.getMobilityConfig().mobilityType || "random",
Expand Down
Empty file modified nebula/frontend/static/js/deployment/situational-awareness.js
100644 → 100755
Empty file.
Empty file modified nebula/frontend/static/js/deployment/topology.js
100644 → 100755
Empty file.
Empty file modified nebula/frontend/static/js/deployment/ui-controls.js
100644 → 100755
Empty file.
Empty file modified nebula/frontend/static/js/deployment/utils.js
100644 → 100755
Empty file.
Empty file modified nebula/frontend/static/js/monitor/monitor.js
100644 → 100755
Empty file.
Empty file modified nebula/frontend/static/js/particles.json
100644 → 100755
Empty file.
Empty file modified nebula/frontend/static/js/particles.min.js
100644 → 100755
Empty file.
Empty file modified nebula/utils.py
100644 → 100755
Empty file.
Empty file modified pyproject.toml
100644 → 100755
Empty file.
Loading