From 304987232ad4b95e15667dcd58cd05fae1132482 Mon Sep 17 00:00:00 2001 From: Ondrej Lukas Date: Tue, 5 Nov 2024 15:12:57 +0100 Subject: [PATCH 1/5] add file hashing method --- utils/utils.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/utils/utils.py b/utils/utils.py index a74cf3d..a2a8dc2 100644 --- a/utils/utils.py +++ b/utils/utils.py @@ -1,5 +1,6 @@ # Utility functions for then env and for the agents # Author: Sebastian Garcia. sebastian.garcia@agents.fel.cvut.cz +# Author: Ondrej Lukas, ondrej.lukas@aic.fel.cvut.cz #import configparser import yaml import sys @@ -16,6 +17,19 @@ import csv from random import randint import json +import hashlib + +def get_file_hash(filepath, hash_func='sha256', chunk_size=4096): + """ + Computes hash of a given file. + """ + hash_algorithm = hashlib.new(hash_func) + with open(filepath, 'rb') as file: + chunk = file.read(chunk_size) + while chunk: + hash_algorithm.update(chunk) + chunk = file.read(chunk_size) + return hash_algorithm.hexdigest() def read_replay_buffer_from_csv(csvfile:str)->list: """ From 03bd35ff710a0bbe29e4ab1b4384861bc7e554ba Mon Sep 17 00:00:00 2001 From: Ondrej Lukas Date: Tue, 5 Nov 2024 15:13:20 +0100 Subject: [PATCH 2/5] compute configuration file hash --- coordinator.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/coordinator.py b/coordinator.py index ea2d657..c73b169 100644 --- a/coordinator.py +++ b/coordinator.py @@ -12,7 +12,7 @@ from env.worlds.network_security_game_real_world import NetworkSecurityEnvironmentRealWorld from env.worlds.aidojo_world import AIDojoWorld from env.game_components import Action, Observation, ActionType, GameStatus, GameState -from utils.utils import observation_as_dict, get_logging_level +from utils.utils import observation_as_dict, get_logging_level, get_file_hash from pathlib import Path import os import signal @@ -174,6 +174,7 @@ def __init__(self, actions_queue, answers_queue, net_sec_config, allowed_roles, self._answers_queue = answers_queue self.ALLOWED_ROLES = allowed_roles self.logger = logging.getLogger("AIDojo-Coordinator") + # world definition match world_type: case "netsecenv": @@ -183,9 +184,7 @@ def __init__(self, actions_queue, answers_queue, net_sec_config, allowed_roles, case _: self._world = AIDojoWorld(net_sec_config) self.world_type = world_type - - - + self._CONFIG_FILE_HASH = get_file_hash(net_sec_config) self._starting_positions_per_role = self._get_starting_position_per_role() self._win_conditions_per_role = self._get_win_condition_per_role() self._goal_description_per_role = self._get_goal_description_per_role() @@ -215,6 +214,10 @@ def episode_end(self)->bool: self.logger.debug(f"End evaluation: {self._agent_episode_ends.values()}") return all(self._agent_episode_ends.values()) + @property + def CONFIG_FILE_HASH(self): + return self._CONFIG_FILE_HASH + def convert_msg_dict_to_json(self, msg_dict)->str: try: # Convert message into string representation From 39dda553fa26390ada2818dfbfcdf1c1de09ddeb Mon Sep 17 00:00:00 2001 From: Ondrej Lukas Date: Tue, 5 Nov 2024 15:16:04 +0100 Subject: [PATCH 3/5] Send the config hash to the agent upon registration --- coordinator.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/coordinator.py b/coordinator.py index c73b169..8eb790d 100644 --- a/coordinator.py +++ b/coordinator.py @@ -386,15 +386,17 @@ def _process_join_game_action(self, agent_addr: tuple, action: Action) -> dict: agent_role = action.parameters["agent_info"].role if agent_role in self.ALLOWED_ROLES: initial_observation = self._initialize_new_player(agent_addr, agent_name, agent_role) + max_steps = self._world._max_steps if agent_role == "Attacker" else None output_message_dict = { "to_agent": agent_addr, "status": str(GameStatus.CREATED), "observation": observation_as_dict(initial_observation), "message": { "message": f"Welcome {agent_name}, registred as {agent_role}", - "max_steps": self._world._max_steps, + "max_steps": max_steps, "goal_description": self._goal_description_per_role[agent_role], - "num_actions": self._world.num_actions + "num_actions": self._world.num_actions, + "configuration_hash": self.CONFIG_FILE_HASH }, } else: From 26f0b5e3f4a894237ce7c03459fd4add6b8d5257 Mon Sep 17 00:00:00 2001 From: Ondrej Lukas Date: Tue, 5 Nov 2024 15:22:28 +0100 Subject: [PATCH 4/5] Update test for player registration --- tests/test_coordinator.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_coordinator.py b/tests/test_coordinator.py index 8568472..2b15ebc 100644 --- a/tests/test_coordinator.py +++ b/tests/test_coordinator.py @@ -92,6 +92,7 @@ def test_join(self, coordinator_init): assert "max_steps" in result["message"].keys() assert "goal_description" in result["message"].keys() assert not result["observation"]["end"] + assert "configuration_hash" in result["message"].keys() # def test_reset(self, coordinator_registered_player): # coord, _ = coordinator_registered_player From eb7ae3db4ec612b5c20f7eed6a237a18aed33635 Mon Sep 17 00:00:00 2001 From: Ondrej Lukas Date: Tue, 5 Nov 2024 15:24:50 +0100 Subject: [PATCH 5/5] Fix ruff checks --- coordinator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/coordinator.py b/coordinator.py index 8eb790d..5839be0 100644 --- a/coordinator.py +++ b/coordinator.py @@ -215,7 +215,7 @@ def episode_end(self)->bool: return all(self._agent_episode_ends.values()) @property - def CONFIG_FILE_HASH(self): + def config_file_hash(self): return self._CONFIG_FILE_HASH def convert_msg_dict_to_json(self, msg_dict)->str: @@ -396,7 +396,7 @@ def _process_join_game_action(self, agent_addr: tuple, action: Action) -> dict: "max_steps": max_steps, "goal_description": self._goal_description_per_role[agent_role], "num_actions": self._world.num_actions, - "configuration_hash": self.CONFIG_FILE_HASH + "configuration_hash": self._CONFIG_FILE_HASH }, } else: